昨天簡單講了 Docker Container 跟 Docker Image 的觀念,今天就來實際的操作看看ㄅ! (」・ω・)」
今天全部在自己的電腦上做,不碰 AWS、零費用:跑幾個指令、開一個網頁、走完一個容器的一生。
先開一個乾淨的工作資料夾,之後所有練習都在裡面:
mkdir -p ~/ironman-lab/day07 && cd ~/ironman-lab/day07
軟體工程師學東西都是從 "hello world" 開始,Docker 也不意外
docker run hello-world
你會看到一段很長的"Hello from Docker! ...",它把 client 把指令送給 daemon、daemon 從 Docker Hub 拉 image、用 image 建 container、把輸出送回終端機,四步自己講完了,剛好對應昨天 Client 和 Server 那張圖。
接著看三個指令的差別:
docker ps # 空的,容器跑完就結束了
docker ps -a # 看得到,狀態是 Exited
docker images # hello-world 這個 image 留在本機

docker ps 只列正在跑的容器。hello-world 印完字程式就結束了,容器的壽命就是它裡面那個程式的壽命,所以要加 -a 才看得到它。image 則是留下來的,下次 docker run 就不用再拉。PS. -a 是 --all 的縮寫。
昨天提到,container 裡面有什麼就能跑什麼,跟你電腦有沒有裝無關。今天用 Node 試試看ㄅ。
node -v
PS. -v 是 --version
像我的是 v22.14.0 的版本,沒裝的話會顯示 command not found,也沒關係,下一步一樣跑得起來。
2. 用容器跑一個不同的版本:
docker run --rm node:24-alpine node -v
我們來拆解這個指令:
docker run:用後面那個 image 建一個容器並執行。--rm:容器跑完自動刪掉,不會像 hello-world 那樣留一個 Exited 的容器在清單裡。node:24-alpine:<image 名稱>,三段是「官方 node image、版本 24、alpine 精簡版 Linux 打底」。PS. 執行後你可能會看到 Unable to find image 'node:24-alpine' locally 因為你本地端沒有這個 image 所以他跑去 Docker Hub 上下載官方的 image
執行完後你會看到印出 v24 開頭的版本,跟電腦上的 v22.14.0 不一樣。電腦沒裝 Node 24,容器裡有,就跑得起來,這就回答了昨天『換一台電腦 Node 版本不同』的問題:版本跟著 image 走。
3. 比一下大小:
docker images

你可以看到 node:24-alpine 大約一百多 MB,hello-world 只有幾 KB。alpine 已經是精簡過的版本,同樣的 node image 不加 alpine 會超過 1GB,明天寫 Dockerfile 挑底圖時會再回來講這件事。
前面提到兩個都是跑完就結束了,現在來跑一個會一直活著的:nginx。它是一個 web server,給它一個資料夾,它就把裡面的檔案當網站送出去,前端 build 出來的靜態檔很多時候最後就是交給它。如果想更加了解什麼是 web server 可以參考這篇。之後在 EC2 上我們也會放一個同類的東西在最前面接流量,今天先在本機認識它。
docker run -d --name web -p 8080:80 nginx
docker ps
跟剛才不一樣的三個參數:
-d:背景執行,終端機不會被它占住。--name web:幫容器取名字,不然 Docker 會隨機給一個。-p 8080:80:把電腦的 8080 接到容器的 80。方向是「外面:裡面」,nginx 在容器裡聽 80,我們從電腦的 8080 進去。這個順序一定會有人搞反,記成「先寫自己這邊」。
docker ps 這次有東西了,STATUS 是 Up,因為 nginx 是一個不會自己結束的程式。
docker logs web
重新整理一次瀏覽器再跑一次,會多一行 GET /,那就是你剛才的請求。
docker exec -it web sh
ls /usr/share/nginx/html
exit
exec 是在跑著的容器裡再執行一個指令,-it 讓它變成互動式的 shell,也就是讓我們可以進到 container 的終端機進行操作。
歡迎頁就是那個資料夾裡的 index.html。看完就把它收掉,順便走一遍容器的一生。
接著來收掉他看看 container 的一生ㄅ
docker stop web
docker ps # 空
docker ps -a # web 還在,狀態 Exited
docker start web
docker ps # 回來了,STATUS 又是 Up
docker rm -f web
docker ps -a # 乾淨
docker images # image 都還在

我們可以看到停掉的 container 不會自己消失,會一直占著名字和磁碟,要 rm 才會走;-f 是連正在跑的一起強制刪,省一次 stop。
最後那行 docker images 是今天最重要,容器刪掉了,image 卻還在。container 是用 image 建出來的執行個體,刪掉容器不會動到 image。
今天跑了三種容器:跑完就結束的 hello-world、借來用一下的 node、一直活著的 nginx,也看到了 log、進去過裡面、走完停看開刪。這些全是跑別人做好的 image。
明天就來自己做 image ㄅ!
資安小提醒:-p 8080:80 預設是綁在電腦的所有網路介面上,回頭看 docker ps 的 PORTS 欄,0.0.0.0 就是這個意思,同一個 Wi-Fi 的人也連得到你的 8080,練習完記得 docker stop;只想給自己用的話寫 -p 127.0.0.1:8080:80。另外只拉 Docker Hub 上標 Official Image 的 image,來路不明的 image 跟來路不明的執行檔是一樣的東西。
docker run 官方文件
docker exec 官方文件