有鑒於工作上接觸到各種啟動 container 的特殊需求,我慢慢地從單一Dockerfie :建立 image 並啟動 container,變成進階版的 docker compose: 一次建立多個 images 並啟動相互關聯的 container,讓容器間彼此互通有無、共同串聯起來形成服務~
(對docker, container還不熟的建議 點我看這篇)
這讓我有個大膽的想法😈,既然 Dockerfile 可以建立 image,那我在 docker compose 的時候能不能用這個建立好的 image 來啟動 container?
答案是:YES!
玩到現在驚覺,當初碰到 docker 就跟小傑與奇犽一樣,剛接觸到念能力一樣,覺得這也不過如此。
事實證明我 too young too simple 了,容器的妙用實在是博大精深,這也是為何現在軟體界都是這種微服務的模式。
就讓西索來教我們登大人吧(容器的水可是很深的喔😵💫)
先來講講使用場景吧
舉個簡單的例子:假設我需要一個可以運行 python 的環境、還有一個 redis server 的環境,我要執行 python script 在 redis 上做一些資料儲存與運算。我一開始可能會這樣子啟動、seperate-compose.yml
會這樣寫:
用指令 docker compose -f seperate-compose.yml up -d
來啟動之後,就可以啟動兩個 container(py-env, redis)
接著進去剛啟動的 py-env 容器,bash 啟動 python環境連看看 redis,成功在redis這個container中塞入一筆資料(Key: “test”, Value: 1)。來敲指令吧~
$ docker exec -it py-env sh #先進入 py-env 並啟動 shell
# python3 #在容器裡運行python
>>> import redis #載入redis套件
>>> r = redis.Redis(host='redis', port=6379) #連進容器的redis
>>> r.set("test", 1) #塞一筆資料看看
True #代表塞入成功!
>>> exit() #退出python
# exit #退出container
接著來 redis 這個容器看一下資料情形吧~一樣敲指令~
$ docker exec -it redis sh
# redis-cli #進入redis client端
127.0.0.1:6379> get test #獲取剛剛的key值: test
"1" # 成功返回Value
127.0.0.1:6379>
BUT…我想要換個做法
這樣我每次都要啟動 py-env, redis這兩個 container 互連才能夠把服務建立起來,我能不能一次到位?只啟動一個 container 就好呢?
i.e 我想要一個 container 同時擁有 python 與 redis 的服務!
眼尖的讀者可發現在前面的seperate-compose.yml
,其實兩個容器的基底image分別是 python:3.9-slim
與 redis:6-alpine3.15
,那要在哪裡找一個基底image、是在 build 的時候同時擁有 python+redis的環境呢?
答案就在一開始,我要自己寫一個 Dockerfile 定義好 image。接著再利用 docker compose 把這個強大的 image 啟動成 container💪
先來看看 Dockerfile吧
首先,用下面這個 Dockerfile 建立起 image,簡單敘述一下裡頭做了些什麼事情:
再來就是 docker compose 的 yml 檔
重頭戲來撰寫 combine-compose.yml
接著執行 docker compose -f combine-compose.yml up -d
來啟動 container
接下來進去 redis 這個 container 玩玩看吧
- 進入容器並啟動shell
$ docker exec -it redis sh
- 啟動python並嘗試在redis中塞入一筆資料,再退出python
/data# python3
>>> import redis
>>> r = redis.Redis(host='redis', port=6379)
>>> r.set("test_comb", 1)
True
>>> exit() - 去redis-server看看資料有沒有成功塞入
/data# redis-cli
127.0.0.1:6379> get test_comb
"1"
如此一氣呵成~都在同一個容器內完成🥴
總結
核心概念就是先建立 image,才能啟動 container。建立 image 的方式可以用現成的 docker pull、或是自己寫 Dockerfile 建立; 啟動 container 的方式可以用一般 docker run 指令、或是本文中 docker compose 的方式一次啟動多個。只要掌握住了,萬變不離其宗😎
以上程式碼都放在 github 上了,有興趣的讀者可以抓下來玩玩看
延伸閱讀
以現今的趨勢,其實還是以啟動多容器來架構整個服務比較常見。我會有這種搞怪的做法,單純是因為我想要在 redis 啟動時可以 config 做一些特殊設定,例如:在每天的半夜12點reset鍵值、或是每隔1小時新增一個鍵值。
這些需求沒有辦法用 redis 本身提供的指令做到,所以我只能另外啟動一個 python 環境運行 python script,來做 redis config 特殊設定。
當然可能還是有redis本身支援的方式,就有勞各位大神如果有更好的做法,還請不吝告知小弟,大家互相學習增長:)