ソフトウェア/docker/覚書 の履歴(No.2)
更新docker について自分用のメモを†
いろいろ検証しないとあやふやなところがあるので間違っているところも多いかもしれません。 すみません。
Dockerfile†
各命令は個別に実行され、都度、新しいイメージが生成されるため、たとえば RUN cd /tmp という命令は続く命令に影響を与えない。
#コメント | |
FROM someone/imagename:tag AS tag_name | "アカウント名/イメージ名:バージョン番号" が基本。公式イメージではアカウント名の部分を省略。 |
RUN command1 && command2 | デフォルトでは Linux では /bin/sh -c で、 Windows では cmd /S /C で処理される。 |
SHELL | RUN で使われるシェルを変更する |
RUN ["/path/cmd", "arg1", "arg2"] | シェルを使わず exec で直接実行される。引数は JSON なので必ず " で囲み、必要に応じて \ をエスケープして \\ にする。環境変数は展開されないし、PATH も効かないためコマンドはフルパスで指定する |
ENV variable_name=default_value | 後に $variable_name あるいは ${variable_name} で参照 |
${variable:-default_value} | variable が定義されていないときは default_value になる |
${variable:+switch_value} | variable が定義されているとき switch_value になる。定義されていなければ空。 |
\$variable | $ は \ でエスケープ可能 |
環境変数の置き換えが有効なコマンド | ADD, COPY, ENV, EXPOSE, FROM, LABEL, STOPSIGNAL, USER, VOLUME, WORKDIR, ONBUILD (RUN が入っていないことに注意! build には環境変数は渡せない) |
ENV で指定した環境変数はコンテナにも引き継がれる | 確認するには docker inspect <image>, 置き換えるには docker run --env <キー>=<値> |
ARG で指定した変数はコンテナに引き継がれない | build 中のみ意味を持つ |
FROM の前にある ARG variable | FROM でのみ利用可能で構築ステージからは参照できない。参照したければ構築ステージにデフォルト値なしの ARG variable を書けば、外の値を引き継げる |
キャッシュ | ADD 命令や COPY 命令より後ろの RUN 命令の内容はキャッシュされない。 |
CMD | RUN と同様にシェル形式と exec 形式の2つの書き方ができる。ENTRYPOINT が設定されていれば、JSON 配列形式で引数を記述する。docker run で上書きされない限り、デフォルトで実行されるコマンドになる |
LABEL multi.label1="value1" multi.label2="value2" other="value3" | docker image inspect で参照可能なイメージのラベル情報を設定する |
LABEL maintainer="SvenDowideit@home.org.au" | 最近は MAINTAINER ではなく LABEL で著者情報を書き込むのが推奨 |
EXPOSE <ポート> [<ポート>/<プロトコル>...] | docker run -P とした際に公開されるポートを指定する?docker run --expose で公開ポートを追加できるし、この指定とは無関係に や docker run -p で任意のポートを公開できる。 |
ADD [--chown=<ユーザ>:<グループ>] <追加元>... <追加先> | 追加元にはワイルドカードが使えるし、リモートや圧縮ファイルも指定できる。 |
COPY [--chown=<ユーザ>:<グループ>] [--from=<イメージ>] <コピー元>... <コピー先> | 別のイメージからコピーすることもできる |
ENTRYPOINT ["実行ファイル", "パラメータ1", "パラメータ2"] | シェル形式だと CMD や run コマンドラインの引数を使えず、シグナルも受け取れないので通常はこの exec 形式にする。 |
build†
LANG:console $ DOCKER_BUILDKIT=1 docker build -f someDockerfile --build-arg ARG=VALUE --pull --rm=true -t tag-name (path|URL|-)
-f someDockerfile | 指定されなければ path/Dockerfile が使われる |
--build-arg ARG=VALUE | Dockerfile 中で ARG で定義された引数に値を設定する |
環境変数 | build には環境変数を渡せないので ARG を使う |
DOCKER_BUILDKIT=1 | BuildKit バックエンドを使う |
--pull | 常に最新のイメージを pull する |
--no-cache | キャッシュを使わず最新の情報でイメージを作成する |
--rm=true | ビルドに成功したら中間コンテナを削除する |
-t tag-name | イメージにタグをつける。複数指定してもいい。 |
-v でボリュームを指定することはできない | 代わりに COPY や ADD を使う |
path の代わりに URL を与える | URL を git clone して、それをコンテキストとして使う |
path の代わりに - とした場合 | $ docker build - < Dockerfile などとできる。 標準入力へ hoge.tar.gz などを突っ込むとちゃんと展開して使われる |
path にあるすべてのファイルが docker に渡される | ファイルが多いとパフォーマンスに影響する。 不必要なファイルを path/.dockerignore に入れておく。 |
返り値 | 成功したら 0、失敗したらエラーコード |
注意点†
docker build が docker run と大きく違うところが2つ
- 環境変数を引き継げないこと
- -v によるボリュームの指定が効かないこと
これらは docker の解説の中でもっともっと強調されるべきだと思う。
そして、この不整合のせいで Dockerfile やイメージ、コンテナの取り回しが非常に悪くなっているので、 何とか統合する方向で解消してほしい。
例えば build に COPY で Gemfile を与えて bundle install しても、 更新された Gemfile.lock はイメージの中にあって、app フォルダを -v でマウントしてしまうと隠れちゃう。それを回避するためにはむちゃくちゃ アクロバティックなことをしなきゃならなくなるんだと思う。
build の環境と run の環境が異なった方が良いことなんてほとんどないはずなので、 ほんとこれ何とかしてほしい。
run†
LANG:console $ docker run -it image
docker 実験†
LANG:console $ cat Dockerfile FROM busybox ENV var1=default RUN echo var1=$var1 $ var1=hello docker build --no-cache . Sending build context to Docker daemon 3.072kB Step 1/3 : FROM busybox ---> 16ea53ea7c65 Step 2/3 : ENV var1=default ---> Running in a6d8c3e7f731 Removing intermediate container a6d8c3e7f731 ---> 73d02c41b6f8 Step 3/3 : RUN echo var1=$var1 ---> Running in db039a001e2a var1=default Removing intermediate container db039a001e2a ---> 672ad5660024 Successfully built 672ad5660024
ん? なんかやっぱりうまく環境変数を渡せてない気がする???
LANG:console $ docker inspect 672ad5660024 [ { "Id": "sha256:672ad5660024782ced68878e68c26dba5d54877d6bbcb6b2051b6e7168d67c4b", "RepoTags": [], "RepoDigests": [], "Parent": "sha256:73d02c41b6f8c9c9ce2c0fe672d1adfa445de303dfa419513746a808ab8d01c2", "Comment": "", "Created": "2021-09-22T13:31:35.877130065Z", "Container": "db039a001e2a0702dae61880f118155732e0ad4dec891e6defc0104efbaaba08", "ContainerConfig": { "Hostname": "", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "var1=default" ], "Cmd": [ "/bin/sh", "-c", "echo var1=$var1" ], "Image": "sha256:73d02c41b6f8c9c9ce2c0fe672d1adfa445de303dfa419513746a808ab8d01c2", "Volumes": null, "WorkingDir": "", "Entrypoint": null, "OnBuild": null, "Labels": null }, "DockerVersion": "20.10.8", "Author": "", "Config": { "Hostname": "", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "var1=default" ], "Cmd": [ "sh" ], "Image": "sha256:73d02c41b6f8c9c9ce2c0fe672d1adfa445de303dfa419513746a808ab8d01c2", "Volumes": null, "WorkingDir": "", "Entrypoint": null, "OnBuild": null, "Labels": null }, "Architecture": "amd64", "Os": "linux", "Size": 1235724, "VirtualSize": 1235724, "GraphDriver": { "Data": { "MergedDir": "/var/lib/docker/overlay2/b4f2f0e969d6cbb29e2b74c6d622ed7b526ff6088949cd48e7d6a98749272892/merged", "UpperDir": "/var/lib/docker/overlay2/b4f2f0e969d6cbb29e2b74c6d622ed7b526ff6088949cd48e7d6a98749272892/diff", "WorkDir": "/var/lib/docker/overlay2/b4f2f0e969d6cbb29e2b74c6d622ed7b526ff6088949cd48e7d6a98749272892/work" }, "Name": "overlay2" }, "RootFS": { "Type": "layers", "Layers": [ "sha256:cfd97936a58000adc09a9f87adeeb7628a2c71d11c4998e6e7f26935fa0cd713" ] }, "Metadata": { "LastTagTime": "0001-01-01T00:00:00Z" } } ]
やはり、
"Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "var1=default" ],
なんてなっていて、環境変数を正しく渡せていないっぽい。
この PATH はコンソールのものと異なるので、どうもコンテナ内で設定されたものっぽい。
LANG:console $ cat Dockerfile FROM busybox ENV var1 RUN echo var1=$var1 $ var1=hello docker build .
Counter: 3230 (from 2010/06/03),
today: 1,
yesterday: 4