シェルスクリプトを使用してDockerコンテナ内でスクリプトを実行する


88

Dockerコンテナを設定するためのシェルスクリプトを作成しようとしています。私のスクリプトファイルは次のようになります。

#!bin/bash

docker run -t -i -p 5902:5902 --name "mycontainer" --privileged myImage:new /bin/bash

このスクリプトファイルを実行すると、新しく呼び出されたbashでコンテナーが実行されます。

次に、上記のシェルスクリプトからすでにコンテナ内にあるスクリプトファイル(test.sh)を実行する必要があります(例:cd /path/to/test.sh && ./test.sh)これを行うにはどうすればよいですか?


1
なぜ使用しないWORKDIRCMD
ダーミット2015

1
おそらく、ここで特権を使用したくないでしょう。参照:stackoverflow.com/questions/36425230/…–
CMP

回答:


123

次を使用して、実行中のコンテナでコマンドを実行できますdocker exec [OPTIONS] CONTAINER COMMAND [ARG...]

docker exec mycontainer /path/to/test.sh

そして、bashセッションから実行するには:

docker exec -it mycontainer /bin/bash

そこから、スクリプトを実行できます。


6
最初に/ bin / bashに入り、次にそのbash内でコマンドを実行する必要がある場合はどうなりますか?
zappy 2015

49
ホストから直接ローカルスクリプトを実行することもできます。docker exec -i mycontainer bash < mylocal.sh これにより、ローカルホストスクリプトが読み取られ、コンテナ内で実行されます。これは他のもの(tarにパイプされた.tgzファイルなど)で行うことができます-コンテナプロセスのstd入力にパイプするために「-i」を使用するだけです。
マーヴィン2017

@Marvin PowerShellの同等のものは何ですか?「<」文字は認識されません。
Nicekiwi

1
私は(ありがたいことに)PowerShellの第一人者ではありませんが、SOをさまよって、stackoverflow.com / a / 11788475/500902を見つけました。だから、多分Get-Content mylocal.sh | docker exec -i mycontainer bash。それがうまくいくかどうかはわかりませんが。
マーヴィン

99

Dockerコンテナが稼働していると仮定すると、次のようにコマンドを実行できます。

docker exec mycontainer /bin/sh -c "cmd1;cmd2;...;cmdn"

2
私はこの答えが好きです。コマンドまたは一連のコマンドを実行するために、Dockerコンテナーにログインする必要はありません。ありがとうございました!
Hatem Jaber 2016年

これをさらに一歩進めて、コマンド全体(/bin/sh -c "cmd1; cmd2; ...; cmdn")をシェル変数の値として渡す方法を知っていますか?'docker run'は、引用符で囲まれた文字列ではなく、単一のコマンドと引用符で囲まれていない個々の引数を期待しているように見えるため、私は尋ねます。
davidA 2016

@meowsqueak:この回答は、既に作成され実行中のコンテナー内で、コンテナーにログインせずに複数のコマンドを実行する方法を示しています。これは自動化に役立ちます。ただし、コンテナの作成時に複数のコマンドを実行する場合(PS:docker runコマンドはコンテナを作成して開始します)、この同じスレッドで回答に従うことでそれを実現できますstackoverflow.com/a/41363989/777617
Cyclops

の代わりにcmd1、forループ全体を渡す必要がありますが;loopステートメントとdoステートメントの後に渡す必要があります。forループ全体を単一のコマンドとして実行するにはどうすればよいcmd1ですか?出来ますか?
ニコラス

19

私はこれと同じ質問に対する答えを探していて、DockerfileソリューションでENTRYPOINTを見つけました。

Dockerfile

...
ENTRYPOINT /my-script.sh ; /my-script2.sh ; /bin/bash

これで、コンテナを起動するとスクリプトが実行され、スクリプトの実行後にbashプロンプトが表示されます。


6

ローカルディレクトリをDockerイメージにマウントし、でスクリプトを入手することもできます.bashrc。新しいシェルごとにスクリプトを実行する場合を除いて、スクリプトは関数で構成されている必要があることを忘れないでください。(これは古くなっています。更新通知を参照してください。)

このソリューションを使用して、Dockerインスタンスの外部でスクリプトを更新できるようにしています。このようにして、変更が発生した場合にイメージを再実行する必要はなく、新しいシェルを開くだけです。(シェルを再び開くことを取り除きました-更新通知を参照してください)

現在のディレクトリをバインドする方法は次のとおりです。

docker run -it -v $PWD:/scripts $my_docker_build /bin/bash

これで、現在のディレクトリがにバインドされます /scriptsDockerインスタンスにます。

(古い).bashrc変更を保存するには、次のコマンドを使用して作業イメージをコミットします。

docker commit $container_id $my_docker_build

更新

この問題を解決して、変更ごとに新しいシェルを開くために、次のことを行います。

dockerfile自体にを追加しRUN echo "/scripts/bashrc" > /root/.bashrc"ます。内部zshrcは、scriptsディレクトリをパスにエクスポートします。スクリプトディレクトリには、1つではなく複数のファイルが含まれるようになりました。これで、変更のたびにサブシェルを開かなくても、すべてのスクリプトを直接呼び出すことができます。

ところで、コンテナの外でも履歴ファイルを定義できます。このようにして、bashの変更をコミットする必要がなくなりました。


遅すぎる..!@javierはすでに簡単な解決策を示しています!! まだまだいい気がします。
zappy 2018年

2
@zappyハビエルの解決策は私にとってこの問題を便利に解決しませんでした-しかし私の解決策は解決しました、Dockerイメージを再起動して更新したくない同様の問題を抱えている人にとっては興味深いと思いました必要な機能を表示します。たとえば、一度に複数のDockerイメージを使用して開発クラスターを起動する場合、それらを常に再起動する必要はありません。
Devpool 2018年

3

実行中のコンテナーが必要ない(またはない)場合は、runコマンドを使用してスクリプトを直接呼び出すことができます。

反復的なtty-i -t引数を削除し、これを使用します。

    $ docker run ubuntu:bionic /bin/bash /path/to/script.sh

これは(テストしませんでした)他のスクリプトでも機能します:

    $ docker run ubuntu:bionic /usr/bin/python /path/to/script.py


0

複数のインスタンスで同じコマンドを実行する場合は、次のようにします。

for i in c1 dm1 dm2 ds1 ds2 gtm_m gtm_sl; do docker exec -it $i /bin/bash -c "service sshd start"; done
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.