ソフトウェア/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 で処理される。
SHELLRUN で使われるシェルを変更する
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 variableFROM でのみ利用可能で構築ステージからは参照できない。参照したければ構築ステージにデフォルト値なしの ARG variable を書けば、外の値を引き継げる
キャッシュADD 命令や COPY 命令より後ろの RUN 命令の内容はキャッシュされない。
CMDRUN と同様にシェル形式と 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=VALUEDockerfile 中で ARG で定義された引数に値を設定する
環境変数build には環境変数を渡せないので ARG を使う
DOCKER_BUILDKIT=1BuildKit バックエンドを使う
--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: 3010 (from 2010/06/03), today: 2, yesterday: 1