簡體   English   中英

如何使用不同的命令啟動停止的 Docker 容器?

[英]How to start a stopped Docker container with a different command?

我想使用不同的命令啟動一個停止的 Docker 容器,因為默認命令崩潰 - 這意味着我無法啟動容器然后使用“docker exec”。

基本上我想啟動一個 shell 以便我可以檢查容器的內容。

幸運的是,我使用 -it 選項創建了容器!

找到您停止的容器 ID

docker ps -a

提交已停止的容器:

此命令將修改后的容器狀態保存到新圖像user/test_image

docker commit $CONTAINER_ID user/test_image

使用不同的入口點啟動/運行:

docker run -ti --entrypoint=sh user/test_image

入口點參數說明: https ://docs.docker.com/engine/reference/run/#/entrypoint-default-command-to-execute-at-runtime

筆記:

上面的步驟只是啟動一個具有相同文件系統狀態的停止容器。 這非常適合快速調查。 但是環境變量、網絡配置、附加卷和其他人員不會被繼承,您應該明確指定所有這些參數。

已從此處借用啟動已停止容器的步驟:(最后評論) https://github.com/docker/docker/issues/18078

編輯此文件(對應於您停止的容器):

vi /var/lib/docker/containers/923...4f6/config.json

更改“路徑”參數以指向您的新命令,例如 /bin/bash。 您還可以設置“Args”參數以將參數傳遞給命令。

重新啟動 docker 服務(注意這將停止所有正在運行的容器):

service docker restart

列出您的容器並確保命令已更改:

docker ps -a

啟動容器並附加到它,你現在應該在你的 shell 中!

docker start -ai mad_brattain

使用 Docker 1.7.1 在 Fedora 22 上工作。

注意:如果您的 shell 不是交互式的(例如,您沒有使用 -it 選項創建原始容器),您可以改為將命令更改為“/bin/sleep 600”或“/bin/tail -f /dev/null”給您足夠的時間來執行“docker exec -it CONTID /bin/bash”作為獲取 shell 的另一種方式。

注意 2:較新版本的 docker 具有 config.v2.json,您需要在其中更改 Entrypoint 或 Cmd(感謝 user60561)。

在入口點腳本的頂部添加一個檢查

Docker 確實需要將此作為一項新功能來實現,但對於您的入口點在成功或失敗后終止的情況,這是另一個解決方法選項,這可能會使調試變得困難。

如果您還沒有 Entrypoint 腳本,請創建一個運行容器所需的任何命令的腳本。 然后,在該文件的頂部,將這些行添加到entrypoint.sh

# Run once, hold otherwise
if [ -f "already_ran" ]; then
    echo "Already ran the Entrypoint once. Holding indefinitely for debugging."
    cat
fi
touch already_ran

# Do your main things down here

為確保cat保持連接,您可能需要提供 TTY。 我正在使用我的 Entrypoint 腳本運行容器,如下所示:

docker run -t --entrypoint entrypoint.sh image_name

這將導致腳本運行一次,創建一個表明它已經運行的文件(在容器的虛擬文件系統中)。 然后您可以重新啟動容器以執行調試:

docker start container_name

當您重新啟動容器時,將找到already_ran文件,導致 Entrypoint 腳本與cat一起停止(它只是永遠等待永遠不會出現的輸入,但保持容器活動)。 然后,您可以執行調試bash會話:

docker exec -i container_name bash

在容器運行時,如果需要以這種方式進行調試,您還可以刪除already_ran並手動執行entrypoint.sh腳本以重新運行它。

我接受了@Dmitriusan 的回答並將其設為別名:

別名 docker-run-prev-container='prev_container_id="$(docker ps -aq | head -n1)" && docker commit "$prev_container_id" "prev_container/$prev_container_id" && docker run -it --entrypoint=bash "prev_container /$prev_container_id"'

將此添加到您的~/.bashrc別名文件中,您將擁有一個漂亮的新docker-run-prev-container別名,它會將您放入前一個容器中的外殼中。

有助於調試失敗的docker build

這並不完全符合您的要求,但如果您只想檢查文件,您可以在停止的容器上使用docker export

mkdir $TARGET_DIR
docker export $CONTAINER_ID | tar -x -C $TARGET_DIR

我的問題:

  • 我用docker run <IMAGE_NAME>啟動了一個容器
  • 然后在這個容器中添加了一些文件
  • 然后我關閉了容器並嘗試使用與上面相同的命令再次啟動它。
  • 但是當我檢查新文件時,它們不見了
  • 當我運行docker ps -a時,我可以看到兩個容器。
  • 這意味着每次我運行docker run <IMAGE_NAME>命令時,都會創建新圖像

解決方案:要在您首先創建的同一個容器上運行,請按照以下步驟操作

  • docker ps獲取容器的容器
  • docker container start <CONTAINER_ID>啟動現有容器
  • 然后你可以從你離開的地方繼續。 例如docker exec -it <CONTAINER_ID> /bin/bash
  • 然后,您可以決定從中創建一個新圖像

我找到了一個簡單的命令

docker start -a [container_name]

這會成功的

或者

docker start [container_name]

然后

docker exec -it [container_name] bash

對我來說,Docker 總是給人留下它是為一個愛好系統創建的印象,它很適合這個。
如果某些事情失敗或不起作用,不要指望有專業的解決方案。

也就是說:Docker 不僅不支持這些基本的管理任務,它還試圖阻止它們。

解決方案:

  1.  cd /var/lib/docker/overlay2/
  2.  find | grep somechangedfile # You now can see the changed file from your container in a hexcoded folder/diff
  3.  cd hexcoded-folder/diff
  4. 創建一個entrypoint.sh (如果存在,請確保備份現有的)

     cat > entrypoint.sh #!/bin/bash while ((1)); do sleep 1; done;

    Ctrl + C

     chmod +x entrypoint.sh
  5.  docker stop docker start

你現在讓你的 docker 容器運行一個無限循環而不是原來的條目,你可以 exec bash 進入它,或者做任何你需要的事情。 完成后停止容器,刪除/重命名您的自定義入口點。

容器啟動后,docker 似乎無法更改入口點。 但是您可以設置自定義入口點,並在下次重新啟動時更改入口點的代碼。

例如,您運行這樣的容器:

docker run --name c --entrypoint "/boot" -v "./boot":/boot $image

這是啟動入口點:

#!/bin/bash
command_a

當您需要使用不同的命令重新啟動 c 時,您只需更改啟動腳本:

#!/bin/bash
command_b

並重新啟動:

docker restart c

docker-compose run --entrypoint /bin/bash cont_id_or_name

(對於 conven,將您的 env、vol 掛載在 docker-compose.yml 中)

或使用 docker run 並手動指定所有參數

沒有指定容器是否正在退出,只是您的代碼崩潰了,您需要查看容器中發生了什么。 如果它沒有退出,這是另一個潛在的解決方案。

使用docker ps獲取容器ID

docker exec -it 665b4a1e17b6 /bin/sh

如果將入口點設置為有問題的東西,也可以按照Dmitriusan的回答中的建議覆蓋它。 還應注意,您可以使用docker attach連接到任何正在運行的容器。 這么多解決方案有不同的解 我只是沒有看到需要提交圖像。 這似乎沒必要。

Docker exec的文檔 - https://docs.docker.com/engine/reference/commandline/exec/

Docker附件的文檔 - https://docs.docker.com/engine/reference/commandline/attach/

進入無法啟動(由於某種原因退出)的容器的外殼(bash / sh):

docker start [CONTAINER] && docker exec -it [CONTAINER] bash

這是可能的,因為&& ,這意味着就在容器無法啟動之前,我們立即運行bash

我有一個 docker 容器,由於 InnoDB 表損壞,MariaDB 容器在啟動時不斷崩潰。

我為解決我的問題所做的是:

  • 將容器中的 docker-entrypoint.sh 復制到本地文件系統(docker cp)
  • 編輯它以包含所需的命令行參數(在我的情況下為--innodb-force-recovery=1)
  • 將編輯后的文件復制回 docker 容器,覆蓋現有的入口點腳本。

圍繞這個進行了很多討論,所以我想我會再添加一個我沒有立即在上面列出的內容:

如果容器入口點的完整路徑已知(或可通過檢查發現),則可以使用“docker cp”將其復制進出已停止的容器。 這意味着您可以將原始文件復制出容器,編輯它的副本以啟動 bash shell(或長睡眠計時器)而不是執行任何操作,然后重新啟動容器。 現在可以使用 bash shell 進一步編輯正在運行的容器以糾正任何問題。 完成將原始入口點的另一個 docker cp 編輯回容器中后,重新啟動應該可以解決問題。

我曾經用它來更正一個“快速修復”,但我已經摸不着頭腦,並且在更正之前無法使用正常的入口點運行容器。

我也同意應該有更好的方法通過 docker 來做到這一點:也許是一個允許備用入口點的“docker restart”選項? 嘿,也許這已經適用於“--entrypoint”? 不確定,沒試過,留給讀者練習,讓我知道它是否有效。 :)

似乎大多數時候人們在修改配置文件時都會遇到這種情況,這就是我所做的。 我試圖繞過 CORS 以使用 Vue SPA 作為我的入口點的 PHP/Apache 服務器。 無論如何,如果你知道你討厭的文件,一個對我有用的簡單解決方案是

  1. 復制您從圖像中刪除的文件:

    docker cp bt-php:/etc/apache2/apache2.conf。

  2. 在本地修復它

  3. 復制回來

    docker cp apache2.conf bt-php:/etc/apache2/apache2.conf

  4. 啟動您的容器備份

  5. *獎勵積分 - 由於此文件正在修改,請將其添加到您的 Compose 或 Build 腳本中,這樣當您做對時,它將被烘焙到圖像中!

docker container start <CONTAINER_ID>

我實際上不同意這兩個答案。 如果您只想查看容器中的內容,則可以運行此命令來獲取shell。 無需更改入口點或任何配置。

docker run -it <image_name> bash

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM