Docker Run ?
Docker技術目前在DevOps中被廣泛使用,我們需要将測試或者建構的代碼和自動化腳本打包成Docker鏡像,然後部署在各運作環境中。而在
CI/CD中,我們常用一些
伺服器,比如Jenkins和GoCD來建構與部署我們的應用,進而實作
的自動化。現在一些CI/CD伺服器也被Docker化運作在真實的實體機上。于是我們需要在CI/CD伺服器的Docker container裡面來建構(build)與運作(run)我們的Docker鏡像,這就涉及到"Docker run Docker"的問題。
一個很自然的想法是,我們是不是需要在CI/CD伺服器鏡像中安裝一個Docker Daemon和Docker指令呢?但是Docker裡面跑Docker總感覺有些蹩腳,額外安裝與運作Docker無疑增加了CI/CD伺服器鏡像的大小,同時還增加Docker的深度。
實際上,我們并不需要在CI/CD伺服器上安裝Docker。通過如下的指令在CI/CD伺服器上運作我們的鏡像:
docker run ... -v /var/run/docker.sock:/var/run/docker.sock \
原理:移花接木
Docker采取的是C/S架構,Docker的成功運作需要Docker Daemon和Docker Client(用戶端)的支援,當我們運作一些docker build等指令時,實際是需要Docker Client連接配接Docker Daemon發送指令,Docker Daemon會在主控端作業系統配置設定檔案、網絡等資源。

Docker in Docker
預設情況下,Docker守護程序會生成一個socket(/var/run/docker.sock)檔案來進行本地程序通信,而不會監聽任何端口,是以隻能在本地使用docker用戶端或者使用Docker API進行操作。一般情況下,我們通路本機的服務往往通過 127.0.0.1:8080 這種IP:端口的網絡位址方式進行通信,而sock檔案是 UNIX 域套接字(UNIX domain socket),它可以通過檔案系統(而非網絡位址)進行尋址和通路的套接字。
從表象上看,上面的指令似乎依然是在“Docker裡面run docker”,其實這是個誤區。docker run提供了 -v 參數讓我們将宿主的檔案映射到docker裡面。比如通過 -v /var/run/docker.sock:/var/run/docker.sock,我們将宿主的Docker Daemon的socket映射到Docker Container裡面;當Container裡面的docker 用戶端通過 /var/run/docker.sock 去操作Docker Daemon時,這些操作已移花接木地轉移到宿主的Docker Daemon上。
延伸:操作遠端主機
既然docker client通過socket方式與本地的Docker Daemon進行通信,那麼我們可以很自然地想到,如果想在其他主機上通過socket連接配接到遠端DockerDaemon,是不是可以遠端操作Docker主機進行鏡像的建構與運作呢?答案是可以的,就需要讓Docker守護程序監聽一個端口,這樣才能實作遠端通信,同時需要修改docker用戶端連接配接的主機是遠端位址而并非本地sock檔案。由于Docker C/S 之間采取Rest API作為通信協定,這為我們使用第三方用戶端(如postman)操作docker乃至自己開發client提供了擴充。
- 原文: Docker In Docker