web-dev-qa-db-ja.com

docker runを介してシェルスクリプトに人数を渡る方法

私は港湾労働者の世界に初めてです。 dockerコンテナを通してコマンドライン引数を受け取るShellスクリプトを起動しなければなりません。例:私のシェルスクリプトは以下のようになります。

#!bin/bash
echo $1

Dockerfileは次のようになります。

FROM ubuntu:14.04
COPY ./file.sh /
CMD /bin/bash file.sh

コンテナの実行中に引数を渡す方法がわかりません

91
Akash Mehta

同じfile.shを使う

#!bin/bash
echo $1

既存のDockerfileを使って画像を構築します。

docker build -t test .

引数abcまたはxyzまたはそれ以外のものを使用してイメージを実行します。

docker run -ti test /file.sh abc

docker run -ti test /file.sh xyz
46
BMW

file.shのこのスクリプトで

#!/bin/bash
echo Your container args are: "$@"

そしてこれDockerfile

FROM ubuntu:14.04
COPY ./file.sh /
ENTRYPOINT ["/file.sh"]
CMD []

あなたはできるはずです:

% docker build -t test .
% docker run test hello world
Your container args are: hello world
101
Partly Cloudy

Dockerでは、この種の情報を渡すための適切な方法は環境変数を使用することです。

同じDockerfileを使って、スクリプトを次のように変更します。

#!/bin/bash
echo $FOO

構築後、次のdockerコマンドを使用してください。

docker run -e FOO="hello world!" test
49
Michael

私が持っているのは実際に物事を実行するスクリプトファイルです。このスクリプトファイルは比較的複雑です。それを "run_container"と呼びましょう。このスクリプトはコマンドラインから引数を取ります。

run_container p1 p2 p3

単純なrun_containerは次のようになります。

#!/bin/bash
echo "argc = ${#*}"
echo "argv = ${*}"

私がやりたいことは、これを「ドッキング」した後、このようなdockerコマンドラインのパラメータでこのコンテナを起動できるようにしたいということです。

docker run image_name p1 p2 p3

パラメータとしてp1 p2 p3を指定してrun_containerスクリプトを実行します。

これが私の解決策です:

Dockerfile:

FROM docker.io/ubuntu
ADD run_container /
ENTRYPOINT ["/bin/bash", "-c", "/run_container \"$@\"", "--"]
16
jkh

ここで相互作用することがいくつかあります。

  1. docker run your_image arg1 arg2CMDの値をarg1 arg2に置き換えます。これはCMDを完全に置き換えるものであり、それ以上の値を追加するものではありません。これが、コンテナ内でbashシェルを実行するためにdocker run some_image /bin/bashがよく見られる理由です。

  2. ENTRYPOINTとCMDの両方の値が定義されている場合、dockerは2つを連結してその連結コマンドを実行することによってコンテナーを開始します。したがって、エントリポイントをfile.shに定義した場合は、file.shにargsとして渡される追加の引数を使用してコンテナを実行できます。

  3. Dockerのエントリポイントとコマンドには2つの構文があります。シェルを起動する文字列構文と、execを実行するjson構文です。シェルは、IOリダイレクション、複数のコマンドのチェーン(&&など)、変数置換などの処理に役立ちます。コンテナーを停止するのに10秒の遅れが見られますが、これが原因であることが多くあります)。また、エントリーポイントとコマンドを連結する場合もあります。エントリポイントを文字列として定義すると、/bin/sh -c "file.sh"が実行されます。これだけで問題ありません。しかし、コマンドが文字列として定義されている場合、コンテナ内で起動されるコマンドとして/bin/sh -c "file.sh" /bin/sh -c "arg1 arg2"のようなものが表示されますが、それほど良くありません。これら2つのオプションがどのように相互作用するかについての詳細は、 こちらの表を参照してください

  4. シェルの-cオプションは単一の引数のみを取ります。それ以降のものはすべて$1$2などとして単一の引数に渡されますが、明示的に引数を渡さない限り、組み込みのシェルスクリプトには渡されません。すなわち/bin/sh -c "file.sh $1 $2" "arg1" "arg2"は機能しますが、/bin/sh -c "file.sh" "arg1" "arg2"は引数なしで呼び出されるため、file.shは機能しません。

まとめると、共通の設計は次のとおりです。

FROM ubuntu:14.04
COPY ./file.sh /
RUN chmod 755 /file.sh
# Note the json syntax on this next line is strict, double quotes, and any syntax
# error will result in a Shell being used to run the line.
ENTRYPOINT ["file.sh"]

そしてそれを実行します。

docker run your_image arg1 arg2

これについては、もう少し詳しく説明します。

14
BMitch

ビルド時に実行したい場合は、

CMD /bin/bash /file.sh arg1

実行時に実行する場合は、次のようにします。

ENTRYPOINT ["/bin/bash"]
CMD ["/file.sh", "arg1"]

それからホストシェルで

docker build -t test .
docker run -i -t test
4
Gilles Quenot

別のオプション...

これを機能させるために

docker run -d --rm $IMG_NAME "bash:command1&&command2&&command3"

dockerfile内

ENTRYPOINT ["/entrypoint.sh"]

entrypoint.sh内

#!/bin/sh

entrypoint_params=$1
printf "==>[entrypoint.sh] %s\n" "entry_point_param is $entrypoint_params"

PARAM1=$(echo $entrypoint_params | cut -d':' -f1) # output is 1 must be 'bash' it     will be tested    
PARAM2=$(echo $entrypoint_params | cut -d':' -f2) # the real command separated by     &&

printf "==>[entrypoint.sh] %s\n" "PARAM1=$PARAM1"
printf "==>[entrypoint.sh] %s\n" "PARAM2=$PARAM2"

if [ "$PARAM1" = "bash" ];
then
    printf "==>[entrypoint.sh] %s\n" "about to running $PARAM2 command"
    echo $PARAM2 | tr '&&' '\n' | while read cmd; do
        $cmd
    done    
fi
0
wagnermarques