Docker-compose使用筆記

Docker-compose使用筆記

前一篇的Dockerfile筆記已經先學會基本的Docker用法,但是docker只能一次操作一個系統,如果要產生MEAN stack不就要下好多個指令嗎? 同事推薦再學一下docker-compse指令,只要寫好yml,你可以一個指令操作好多個docker container,關閉時也很簡單。

以下搭配我已經建立好的php-mariadb的docker-compose來講解

docker-compose.yml

docker-compose預設使用docker-compose.yml檔案,如果是別的檔名就要用-f來指令yml檔案

yml檔案是一種簡單得檔案結構,基本上由 "指令" : "值" 構成,縮排則是代表隸屬規則,而一個簡單的docker-compose檔案會包含:

  1. 版本version
  2. 服務services
版本我們使用當下Ubuntu 20.04可取得的最高版本3.8,更多說明就請參考官網。服務方面我們是要建立一個帶有mysql社群版資料庫的mariadb,使用php語言的apache網頁伺服器環境。

服務包含兩個
  • db使用的mariadb官方提供在docker hub上的image,所以用image來指定。
  • php需要客製化功能,所以不能用image指令,改用build來引用自訂的dockerfile。這部份就回到dockerfile的寫法,所以學會docker-compose就也會用到docker的基本知識。
我習慣在各服務中寫上container_name,因為這樣之後就可以用固定的名稱查看container。

你會看到我的範例還有其他的部份,分別是
  1. 網路networks
  2. 儲存volumes

而php因為會使用到mariadb資料庫,所以在php與db服務有相依性,會用depends_on來指定。然後因為兩個服務之間必須要能夠連線,所以要設定networks讓兩者網路可以連通。

在php服務中用volumes指定專案src目錄掛載到/var/www/html,所以php的程式碼或其他靜態檔案只要放在src目錄下就會可以使用。

再者因我們用到DB,docker預設每次啟動都會用臨時空間來執行container,之後你就會發現DB儲存的資料怎會消失,就是因為沒有建立儲存空間,所以我這用volumes來建立儲存空間。

yml的port是會映射到host,如果你的container不需要給host存取就不用設定,例如這裡db就不是一定要寫這個映射

yml的environment部份是,docker compose預設是會載入.env檔案,所以我們可以用${env-name}來存取變數或是host內的環境變數,如果你是要其他檔名的env檔案,則需要手動以env_file指定檔案

      DB_HOST: backend-db

      DB_NAME: ${DB_NAME}

      DB_USERNAME: ${DB_USERNAME}

      DB_PASSWORD: ${DB_PASSWORD}

注意:我實測你用build建立image,compose預設載入的.env變數不會套用進去,所以如果環境變數也要讓dockerfile使用,則yml要用env_file指定載入.env檔案

注意:我實測env_file和environment之間寫的順序沒有關係,所以先寫env_file載入得環境變數無法被後寫的environment中取用,反之亦然。

用docker-compose啟動

docker-compose up -d

會使用-d是因為我們是一個網頁應用服務,要讓服務在背景跑。如果你是想要debug或是跑一些小程式就不用-d。

如果你正在建構你自己的yml檔而不斷反覆測試時,記得用--build來產生新的。

docker-compose up -d --build

注意:如果你還在建構yml檔,記得每次改yml前都要先關閉服務再改yml,不然compose關閉可能會不正確,導致殘留一堆臨時的container或volumne等等資源導致你之後的建置會失敗。

用docker-compose關閉

docker-compose down

down就會逐一的關閉你的服務,如果你的服務無法正常關閉,還可以用-f強制關掉它。

注意:帶-v可以讓compose在關閉時一併清除volumes,如果你是有帶db的千萬不要用這個,不然你儲存的資料就都會消失啦!

docker-compose down -v

查看網路狀態

如果你發現php沒有辦法連線到db,那就是網路出了問題,就要先查看網路,看container是否有被納入該網路

docker network inspect my-bus

my-bus是我寫在network中的name,你如果沒有寫network,compose預設也會產生一個的網路名稱。

另外會用下面指令來查看container各自的IP

docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' backend-db

docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' frontend-web

查看container系統LOG

docker logs frontend-web

docker logs backend-db

進入運行中的container

docker exec -it frontend-web sh

docker exec -it backend-db sh

上面指令是開sh,不過有些系統是開bash,端看你的系統內建哪種

Volume檔案在哪裡?

在/var/lib/docker/volumes/中,不過從docker開始就只提供root存取,所以要顯示裡頭的檔案你需要用sudo指令

sudo ls /var/lib/docker/volumes/{你的container名稱}


題外話
Ubuntu上使用docker建議是跟隨以下指引給予docker root權限

留言