我如何在 Docker 中運行 Docker 以及它的結果

大家好! 在他的 上一篇文章,我承諾會談論在 Docker 中運行 Docker 以及使用本課程的實際方面。 是時候兌現你的承諾了。 經驗豐富的開發人員可能會反對需要在 Docker 內部使用 Docker 的人只需將 Docker 守護程式套接字從主機轉送到容器中,這在 99% 的情況下就足夠了。 但不要急於向我扔 cookie,因為我們將討論在 Docker 內部實際運行 Docker。 此解決方案有許多可能的應用,本文將介紹其中之一,因此請坐下來,將手臂伸直在身前。

我如何在 Docker 中運行 Docker 以及它的結果

開始

這一切都始於5 月的一個下雨的夜晚,當時我正在清理在Digital Ocean 上以24 美元租用的機器,由於Docker 已用其映像和容器填滿了所有XNUMX GB 的可用磁碟空間,因此該機器被凍結。 諷刺的是,所有這些圖像和容器都是暫時的,只需要在每次發布新版本的程式庫或框架時測試我的應用程式的效能。 我嘗試編寫 shell 腳本並設定 cron 計劃來清理垃圾,但這並沒有幫助:每次它都不可避免地以我的伺服器磁碟空間被耗盡和伺服器掛起(最多)而告終。 在某個時候,我看到一篇關於如何在容器中執行 Jenkins 以及如何透過轉送到容器中的 docker 守護程式套接字來建立和刪除建置管道的文章。 我喜歡這個想法,但我決定更進一步,嘗試在 Docker 中直接執行 Docker。 當時,在我看來,下載 Docker 映像並為在另一個容器(我們稱之為暫存容器)內測試所需的所有應用程式建立容器是一個完全合乎邏輯的解決方案。 這個想法是使用 -rm 標誌啟動一個暫存容器,該容器在停止時會自動刪除整個容器及其所有內容。 我修改了 Docker 本身的 Docker 映像(https://hub.docker.com/_/docker),但事實證明它太麻煩了,我從來沒有設法讓它按照我需要的方式工作,我想自己一路走下去。

實踐。 視錐細胞

我開始讓容器按照我需要的方式工作,並繼續我的實驗,最終長出了無數的花蕾。 我自虐的結果是下面的演算法:

  1. 我們以互動模式啟動 Docker 容器。

    docker run --privileged -it docker:18.09.6

    注意容器的版本,向右或向左移動,你的 DinD 就會變成南瓜。 事實上,當新版本發佈時,事情經常出問題。
    我們必須立即進入外殼。

  2. 我們試圖找出哪些容器正在運行(答案:無),但無論如何讓我們運行命令:

    docker ps

    你會有點驚訝,但事實證明 Docker 守護程式甚至沒有運行:

    error during connect: Get http://docker:2375/v1.40/containers/json: dial tcp: lookup docker on 
    192.168.65.1:53: no such host

  3. 我們自己運行一下:

    dockerd &

    另一個令人不愉快的驚喜:

    failed to start daemon: Error initializing network controller: error obtaining controller instance: failed 
    to create NAT chain DOCKER: Iptables not found

  4. 安裝 iptables 和 bash 軟體包(在 bash 中工作比在 sh 中工作更愉快):

    apk add --no-cache iptables bash

  5. 讓我們啟動 bash。 最後我們回到了平常的外殼

  6. 讓我們嘗試再次啟動 Docker:

    dockerd &

    我們應該看到一長串日誌,結尾為:

    INFO[2019-11-25T19:51:19.448080400Z] Daemon has completed initialization          
    INFO[2019-11-25T19:51:19.474439300Z] API listen on /var/run/docker.sock

  7. 按 Enter 鍵。 我們又回到了狂歡。

從現在開始,我們可以嘗試在 Docker 容器內啟動其他容器,但如果我們想在 Docker 容器內啟動另一個 Docker 容器,或者出現問題導致容器崩潰怎麼辦? 一切重新開始。

自己的 DinD 容器和新實驗

我如何在 Docker 中運行 Docker 以及它的結果
為了避免一遍又一遍地重複上述步驟,我創建了自己的 DinD 容器:

https://github.com/alekslitvinenk/dind

有效的 DinD 解決方案使我能夠在 Docker 內遞歸運行 Docker 並進行更多冒險實驗。
我現在將描述一個這樣的(成功的)運行 MySQL 和 Nodejs 的實驗。
最不耐煩的人也能看到這裡的狀況

那麼,讓我們開始吧:

  1. 我們以互動模式啟動 DinD。 在此版本的 DinD 中,我們需要手動映射子容器可以使用的所有連接埠(我已經在處理這個問題了)

    docker run --privileged -it 
    -p 80:8080 
    -p 3306:3306 
    alekslitvinenk/dind

    我們進入 bash,從中我們可以立即開始啟動子容器。

  2. 啟動MySQL:

    docker run --name mysql -e MYSQL_ROOT_PASSWORD=strongpassword -d -p 3306:3306 mysql

  3. 我們以與本地連接資料庫相同的方式連接到資料庫。 讓我們確保一切正常。

  4. 啟動第二個容器:

    docker run -d --rm -p 8080:8080 alekslitvinenk/hello-world-nodejs-server

    請注意,連接埠映射將準確無誤 8080:8080,因為我們已經將主機到父容器的連接埠 80 對應到連接埠 8080。

  5. 我們在瀏覽器中存取本機主機,確保伺服器回應“Hello World!”

就我而言,嵌套 Docker 容器的實驗結果非常積極,我將繼續開發該專案並將其用於暫存。 在我看來,這是一個比 Kubernetes 和 Jenkins X 更輕量級的解決方案。但這是我的主觀意見。

我想這就是今天文章的全部。 在下一篇文章中,我將更詳細地描述在 Docker 中遞歸運行 Docker 並將目錄深入到嵌套容器中的實驗。

聚苯乙烯 如果您覺得這個專案有用,請在 GitHub 上給它一個 star,fork 它並告訴您的朋友。

Edit1 更正了錯誤,重點關注 2 個視頻

來源: www.habr.com

添加評論