ひゃまだのblog

ひゃまだ(id:hymd3a)の趣味のブログ

DockerのDockerfileとrun、execのオプションの便利技

(2024-01-23 初稿 - )

はじめに

Dockerを使い始めて1年以上になるのに、人様の作ったDokerfileやrun、execのオプションを見て、なるほどと感心することばかり。何か新しいことをやろうとする度に、新しいオプションや発見がある感じ。

しかし、残念なことに筆者はすぐに忘れてしまうので、ここにメモを残す。

なお、このページはDockerの網羅的なマニュアルでは無く、筆者が躓いたり、便利だと思ったオプションのみを記述しているのであしからず。

Dockerfileのオプション

ENV DEBIAN_FRONTEND noninteractive

Dockerfile内でapt-get install しようとすると、対話的なインストールが必要なパッケージの場合はうまくインストールできない。

筆者が経験したパッケージは、libgl1-mesa-dev 等でタイムゾーンを聞かれるので、インストールが途中で止まってしまう。

そんなときは、ENV DEBIAN_FRONTEND noninteractive オプションを付ければよいのだが、docker内の環境だとしても、この環境変数を安易に全体につけるべきではないとのこと。具体的には、以下のサイトを参照のこと。

具体的には、対話的なパッケージのインストールが必要な部分のみ以下のようにインストールすることにした。

RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y libgl1-mesa-dev 

Runのオプション

終了後に削除( --rm)

コンテナからExitし、利用したコンテナが不要の場合は --rm オプションを付けることにより、終了後に削除してくれる。

本オプションがない場合は、docker ps -a で全てのコンテナを表示させ、目的のコンテナを docker rm コンテナ名(or ID)で削除する必要がある。

ちなみに、コンテナの削除に時間が掛かるが、docker rm -f コンテナ名(or ID)とすると、即座に削除できる。

コンテナの名前 --name hogehoge

長く利用するコンテナや似た機能で少しずつ異なるコンテナを作成する場合は、自分で名前を付けた方が、管理しやすくなる。

--name hogehoge

現在のディレクトリの共有 -v $PWD:/work 

コンテナ内にスクリプトやデータを多数引き渡す必要がある場合は、あるディレクトリにまとめて保存しておき、コンテナをrunするときにディレクトリごと引き渡す方法が効率的だ。

筆者は、tensoroflowやWebサーバ関連のスクリプト等を保存するディレクトリを決めた後、そのディレクトリをカレントディレクトリにしてから、runコマンドで起動している。このためのオプションは、以下のとおりになる。

-v $PWD:/work

コンテナ内では、/work(任意の名前で良い)にアクセスすれば、必要なスクリプトやデータを利用することができる。

フォントの共有 -v /usr/share/fonts:/usr/share/fonts

筆者は、まだ困ったことは無いが、コンテナ内のフォントが不足して表示が□(トーフ)になってしまうことがある。

様々なフォントをコンテナ内にインストールするのは無駄なので、ホスト側にあるフォンを共有することにより、フォントのトラブルを回避することができる。

-v /usr/share/fonts:/usr/share/fonts

ディスプレイの共有 -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix

コンテナ内でGUI表示をするプログラムを利用する場合は、ディスプレイを共有する必要がある。そのためのオプションは、以下のとおり。

-e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix

なお、ホスト側では、忘れずに xhost + する必要がある。

$ xhost +

本来であれば、上記サイトにあるとおり、以下のように起動するコンテナのみに限定するように許可することが望ましい。

$ xhost +local:$(docker inspect --format='{{ .Config.Hostname }}' [コンテナID])

/etc/hostsへのホストの追加

ごく少数のホストを /etc/hosts に追加するオプションは以下のとおり。

ホストの追加 少ない場合

--add-host=fuga:192.168.xxx.xxx

ただし、追加するホストが多い場合は、予めカレントディレクトリに hosts ファイルを作成しておき、以下のとおり共有する方法が簡単である。

ホストの追加 多い場合

-v ./hosts:/etc/hosts

なお、ホスト側の ./ は必要なので付け忘れないように。

ユーザ、グループの共有 -u $(id -u):$(id -g) 

rootlessモードやコンテナ内にホストのユーザーを引き継ぐには、以下のオプションを付加する。

-u $(id -u):$(id -g) 

ただし、idが引き継がれる名無しさんになってしまうので、ユーザ名やグループ名も引き継ぐ場合は、以下のとおりホスト側のpsswdとgroupsファイルを共有する。

-v /etc/passwd:/etc/passwd:ro
-v /etc/group:/etc/group:ro

また、万が一の書き換えに備えて :ro リードオンリーオプションも併せて付加すると良い。

メモリの追加  --shm-size=2gb  

yolov5で物体検出を行ったときに、メモリ不足でプログラムが途中で終了してしまった。調べると、Dockerはデフォルトでは 16MB のメモリで起動するようである。

そのようなときには、メモリ余裕を持たせて起動する。

--shm-size=2gb

execのオプション

ログインシェルの実行 --login

Dockerで、execのオプションは、あまり使ったことがない。

以前、コンテナ内の .profile にpathの設定を追加して、コンテナを起動したが、一向にpathが追加されない。

調べてみると、execで起動する際に、 --login オプションを追加することで、.profileを実行してくれて、pathもめでたく設定された。

exec コンテナ名 --login

おわりに

以上、筆者が使ってみて便利だと思ったDockerのオプションをメモしてみた。

また、何か気がついたら追記する。 

関連ページ