Docker
Docker は軽量コンテナとしてあらゆるアプリケーションを詰めて運んで実行できるユーティリティです。
目次
- 1 インストール
- 2 使用法
- 3 設定
- 4 イメージ
- 5 NVIDIA GPU で GPU アクセラレートされた Docker コンテナを動かす
- 6 便利なヒント
- 7 クロスコンパイルに buildx を使う
- 8 Docker とイメージの削除
- 9 トラブルシューティング
- 9.1 Btrfs ファイルシステムで Docker イメージを消去
- 9.2 docker0 ブリッジが IP を取得できない / コンテナからインターネットにアクセスできない
- 9.3 デフォルトで使用できるプロセスやスレッドの数が少なすぎる
- 9.4 Error initializing graphdriver: devmapper
- 9.5 Failed to create some/path/to/file: No space left on device
- 9.6 カーネル 4.19.1 で Invalid cross-device link
- 9.7 virtualbox ドライバーを使用したときに Docker-machine が仮想マシンの作成に失敗する
- 9.8 Docker を起動すると KVM のブリッジネットワークが壊れる
- 10 参照
インストール
Docker イメージを pull し Docker コンテナを実行するには、Docker Engine が必要です。Docker Engine には、コンテナを管理するデーモンや docker
CLI フロントエンドが含まれています。docker パッケージをインストールしてください。開発版は docker-gitAUR パッケージをインストールしてください。次に、docker.service
を開始/有効化して、動作することを確認してください:
# docker info
アクティブな vpn 接続がある場合、docker サービスの起動に失敗することがあることに注意してください。VPN と Docker のブリッジネットワークやオーバーレイネットワークの間で IP が競合するからです。このような場合、docker サービスの起動前に vpn を切断してみてください。その後すぐに vpn に再接続できます。ネットワークの衝突解除を試してみることも可能です (解決策については、 [1] や [2] をご覧ください)。
次に、コンテナが動作することを検証します。次のコマンドは、最新の Arch Linux イメージをダウンロードし、そのイメージを使ってコンテナの中で Hello World プログラムを実行します:
# docker run -it --rm archlinux bash -c "echo hello world"
docker
CLI コマンドを非 root ユーザとして実行できるようにしたい場合は、ユーザーを docker
グループに追加して、ログインし直し、docker.service
を再起動してください。
Docker Compose
Docker Compose (日本語訳ページ) は Docker Engine の代替 CLI フロントエンドです。(例として) docker run
のオプションを使うスクリプトではなく、docker-compose.yml
YAML ファイルを使ってコンテナのプロパティを指定します。これは、しばしば使用されたり複雑な設定を持っていたりするサービスを何度も設定する際に便利です。Docker Compose を使うには、docker-compose をインストールしてください。
Docker Desktop
Docker Desktop は、Linux 仮想マシン内で Docker Engine を実行するプロプライエタリなデスクトップアプリケーションです。Kubernetes クラスタや脆弱性スキャナなどの追加の機能が含まれています。このアプリケーションは、macOS や Windows を使って Docker コンテナを開発するソフトウェア開発チームにとって便利です。このアプリケーションの Linux 移植は比較的新しく、Docker の CLI フロントエンドを補完します [3]。Arch 向けの実験的なパッケージは Docker によって直接提供されています; 詳細は マニュアル (日本語訳ページ) を見てください。残念ながら、そのパッケージには docker-compose パッケージと衝突するファイルが含まれているため、docker-compose がインストールされている場合はまずそれを削除する必要があります。
また、Docker Desktop を実行するには、Linux システム要件 (日本語訳ページ) を満たしている必要があります (要件には KVM による仮想化サポートが含まれています)。Gnome でのトレイアイコンを有効化するには、gnome-shell-extension-appindicator が必要です。
最後に、ファイル共有サポートは、ユーザとグループの id を /etc/subuid
と /etc/subgid
を通してマッピングする必要があります。詳細は Docker Desktop For Linux ファイル共有指示書 (日本語訳ページ) を見てください。
使用法
Docker は複数のパーツから成ります:
- Docker デーモン (Docker Engine とも呼ばれています)。
docker.service
として実行されるプロセスです。Docker API を提供し、Docker コンテナを管理します。 docker
CLI コマンド。ユーザがコマンドラインを通して Docker API と対話し、Docker デーモンを管理できるようにします。- Docker コンテナ。Docker API を通して要求された通りに Docker デーモンが起動・管理する、名前空間で隔離されたプロセスです。
通常、ユーザは docker
CLI コマンドを実行することで Docker を使用します。コマンドは Docker デーモンにアクションの実行を要求し、Docker コンテナを管理します。クライアント (docker
)、サーバ (docker.service
)、コンテナ間の関係を理解することは、Docker を正しく管理するために重要です。
Docker デーモンが停止/再起動した場合、現在実行中の Docker コンテナもすべて停止/再起動されることに注意してください。
Docker API にリクエストを送信して、docker
CLI コマンドを使わずに Docker デーモンを制御することも可能です。詳細は Docker API 開発ドキュメントを見てください。
使用法に関するドキュメントは the Docker Getting Started guide (日本語訳ページ) を見てください。
設定
設定ファイル /etc/docker/daemon.json
を使うか、docker.service
systemd ユニットにコマンドラインフラグを追加することで、Docker デーモンを設定することができます。Docker 公式ドキュメント (日本語訳ページ) によると、設定ファイルによる方法が推奨されています。コマンドラインフラグの方を使いたい場合は、systemd のドロップインファイル を使って、docker.service
の ExecStart
ディレクティブを上書きしてください。
daemon.json
のオプションに関する詳細は、dockerd のドキュメント (日本語訳ページ) を見てください。
ストレージドライバー
ストレージドライバー (日本語訳ページ) は、Docker ホスト上でイメージとコンテナをどのように格納し管理するかを制御します。デフォルトの overlay2
ドライバはパフォーマンスが良く、最近の Linux カーネルとファイルシステムすべてで良い選択肢です。古い Linux カーネルとの互換性のために devicemapper
や aufs
などのレガシーなドライバがありますが、Arch Linux の overlay2
ではなくこれらを使う利点はありません。
btrfs や ZFS のユーザは btrfs
や zfs
のドライバを使用できます。それぞれのドライバは、これらのファイルシステムのユニークな機能を活用します。詳細とステップ・バイ・ステップの説明は btrfs ドライバ (日本語訳ページ) と zfs ドライバ (日本語訳ページ) のドキュメントを見てください。
デーモンのソケット
デフォルトで、Docker デーモンは Unix ソケット /var/run/docker.sock
を用いて Docker API を提供します。ほとんどの場合、この方法は適切です。
さらに TCP ソケットをリッスンするようにデーモンを設定できます。これにより、他のコンピュータからリモートで Docker API にアクセスできるようになります [4]。そうすることで、ホストマシン上の docker
コマンドから Linux 仮想マシン (Windows や macOS システム上の Arch 仮想マシン) 上の Docker デーモンにアクセスできるようになり、便利です。
デフォルトの docker.service
ファイルは -H
フラグをデフォルトでセットします。そして、フラグと /etc/docker/daemon.json
ファイルの両方にオプションが存在する場合、Docker は起動しません。なので、ソケットの設定を変更する最も単純な方法は、ドロップインファイルを使うことです。以下は、ポート 2376 上に TCP ソケットを追加します:
/etc/systemd/system/docker.service.d/execstart.conf
[Service] ExecStart= ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2376
systemd デーモンをリロードし、docker.service
を再起動して変更を適用してください。
HTTP プロキシ
HTTP プロキシを使うために設定すべきなのは、Docker デーモンと Docker コンテナです。
Docker デーモンのプロキシ設定
HTTP プロキシを設定するための systemd ドロップインユニットの設定に関する Docker ドキュメント (日本語訳ページ) を見てください。
Docker コンテナのプロキシ設定
docker
CLI を使用して作成されたすべてのコンテナに対してプロキシを自動で設定する方法は プロキシ設定に関する Docker ドキュメント (日本語訳ページ) を見てください。
DNS の設定
デフォルトでは、docker はホストマシンにある resolv.conf
と同じ中身の resolv.conf
をコンテナに作成します。その際、ローカルアドレス (例: 127.0.0.1
) は消されます。それによって resolv.conf
が空ファイルになった場合、Google の DNS サーバー が記述されます。dnsmasq などのサービスを利用して名前を解決するようにしたい場合、設定が消されないように docker のネットワークインターフェイス用にエントリを /etc/resolv.conf
に追加する必要があります。
systemd-networkd 上に手動で定義したネットワークで Docker を実行
バージョン 220 以上の systemd-networkd を使ってネットワークを手動設定している場合、Docker で起動したコンテナがネットワークにアクセスできない場合があります。バージョン 220 から、ネットワークの転送設定 (net.ipv4.conf.<interface>.forwarding
) はデフォルトで off
です。この設定で IP フォワーディングが使えません。また、コンテナの中で Docker によって有効になる net.ipv4.conf.all.forwarding
の設定と衝突します。
インターネットにアクセスするには、Docker のホスト側で /etc/systemd/network/
にある <interface>.network
ファイルを編集して IPForward=kernel
を追加してください:
/etc/systemd/network/<interface>.network
[Network] ... IPForward=kernel ...
上記の設定でコンテナから IP フォワーディングが使えるようになります。
イメージの置き場所
デフォルトでは、docker のイメージは /var/lib/docker
に保存されます。置き場所は別のパーティションに移動することが可能です。
まず、docker.service
を停止してください。
docker イメージを起動したことがある場合、イメージが完全にアンマウントされていることを確認します。そうしたら、イメージを /var/lib/docker
から好きな場所に移動してください。
その後、docker.service
のドロップインスニペットを作成して、ExecStart
に -g
パラメータを追加してください:
/etc/systemd/system/docker.service.d/docker-storage.conf
[Service] ExecStart= ExecStart=/usr/bin/dockerd -g /path/to/new/location/docker -H fd://
安全ではないレジストリ
もしプライベートレジストリに自己署名証明書を使うことに決めた場合、あなたが信頼すると宣言するまで Docker はその使用を拒否します。docker.service
のドロップインスニペットを追加して、--insecure-registry
パラメータを dockerd
に追加してください:
/etc/systemd/system/docker.service.d/override.conf
[Service] ExecStart= ExecStart=/usr/bin/dockerd -H fd:// --insecure-registry my.registry.name:5000
Docker rootless
docker を rootless モードで(つまり、rootとしてではなく、通常ユーザとして)実行するには、docker-rootless-extras-binAUR パッケージをインストールします。
/etc/subuid
と /etc/subgid
に ユーザ名/グループ名、開始 UID/GID、そして UID/GID 範囲を設定し、再割り当てユーザ/グループに割り当てます:
/etc/subuid
your_username:165536:65536
/etc/subgid
your_username:165536:65536
docker.socket
ユーザユニット を 有効化します。これにより、docker は systemd の socket activation を利用して開始されます。
最後に docker ソケットの環境変数を設定します:
$ export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock
イメージ
Arch Linux
以下のコマンドは archlinux x86_64 イメージを pull します。これはネットワークなどを落とした Arch コア環境です:
# docker pull archlinux
README.md も見てください。
完全な Arch ベースは、上記からリポジトリを clone し、独自のイメージをビルドしてください。
$ git clone https://gitlab.archlinux.org/archlinux/archlinux-docker.git
パッケージ devtools、fakechroot、fakeroot はインストールされていることに注意してください。
ベースイメージをビルドするには:
$ make image-base
Alpine Linux
Alpine Linux は、(特に静的バイナリとしてコンパイルされたソフトウェアための) 小さなコンテナイメージとして人気の選択肢です。以下のコマンドは最新の Alpine Linux イメージを pull します:
# docker pull alpine
Alpine Linux は、ほとんどの Linux ディストリビューションで使用されている glibc libc 実装ではなく、musl libc 実装を使用します。Arch Linux は glibc を使用するので、Arch Linux ホストと Alpine Linux コンテナの間には機能的な違いが一定数存在し、ソフトウェアのパフォーマンスと正確性に影響を与えます。これらの違いのリストは、ここでドキュメント化されています。
Arch Linux (または glibc を使用する他のシステム) でビルドされた動的リンクのソフトウェアは、Alpine Linux (または異なる libc を使用する他のシステム) 上で実行すると、バグとパフォーマンス上の問題を生じる場合があります。例は、[5]、[6]、[7] を見てください。
CentOS
次のコマンドは最新の centos イメージを pull します:
# docker pull centos
各 CentOS リリースで利用可能なタグの完全なリストは Docker Hub ページを見てください。
Debian
次のコマンドは最新の debian イメージを pull します:
# docker pull debian
(各 Debian リリースの標準バージョンとスリムバージョンの療法を含む) 利用可能なタグの完全なリストは Docker Hub ページを見てください。
Distroless
Google は、パッケージマネージャやシェルなどの OS コンポーネントの無い最小イメージである distroless イメージをメンテナンスしています。これにより、ソフトウェアをパッケージングするためにイメージのサイズを非常に小さくできます。
イメージのリストと様々なプログラミング言語での使用法に関する指示は GitHub README を見てください。
NVIDIA GPU で GPU アクセラレートされた Docker コンテナを動かす
NVIDIA Container Toolkit を使う (推奨)
Docker バージョン 19.03 より、NVIDIA GPU が Docker デバイスとしてネイティブにサポートされています。NVIDIA GPU を活用するコンテナの実行方法として NVIDIA Container Toolkit が推奨されています。
nvidia-container-toolkitAUR パッケージをインストールしてください。次に、docker を再起動してください。これで、--gpus
オプションを使うことで、NVIDIA GPU を使用するコンテナを実行できるようになります:
# docker run --gpus all nvidia/cuda:11.3.0-runtime-ubuntu20.04 nvidia-smi
コンテナ内でいくつの GPU を有効化するかを指定するには:
# docker run --gpus 2 nvidia/cuda:11.3.0-runtime-ubuntu20.04 nvidia-smi
どの GPU を使用するかを指定するには:
# docker run --gpus '"device=1,2"' nvidia/cuda:11.3.0-runtime-ubuntu20.04 nvidia-smi
あるいは
# docker run --gpus '"device=UUID-ABCDEF,1"' nvidia/cuda:11.3.0-runtime-ubuntu20.04 nvidia-smi
コンテナで使用する機能 (グラフィックス、計算、...) を指定するには (とはいえ、この方法が使用されるのは稀です):
# docker run --gpus all,capabilities=utility nvidia/cuda:11.3.0-runtime-ubuntu20.04 nvidia-smi
NVIDIA Container Runtime を使う
nvidia-container-runtimeAUR パッケージをインストールしてください。次に、/etc/docker/daemon.json
を編集して NVIDIA ランタイムを登録してください:
/etc/docker/daemon.json
{ "runtimes": { "nvidia": { "path": "/usr/bin/nvidia-container-runtime", "runtimeArgs": [] } } }
そして、docker を再起動してください。
ランタイムは、dockerd にコマンドラインオプションを渡すことでも登録できます:
# /usr/bin/dockerd --add-runtime=nvidia=/usr/bin/nvidia-container-runtime
その後、GPU アクセラレートされたコンテナを実行するには:
# docker run --runtime=nvidia nvidia/cuda:9.0-base nvidia-smi
あるいは (以下の方法は Docker バージョン 19.03 およびそれ以降が必要です):
# docker run --gpus all nvidia/cuda:9.0-base nvidia-smi
README.md も見てください。
nvidia-docker を使う (非推奨)
nvidia-docker は NVIDIA Container Runtime のラッパーです。デフォルトで NVIDIA ランタイムを登録し、nvidia-docker コマンドを提供します。
nvidia-docker を使うには、nvidia-dockerAUR パッケージをインストールし、docker を再起動してください。NVIDIA GPU サポートのあるコンテナは以下の方法で実行できます:
# docker run --runtime=nvidia nvidia/cuda:9.0-base nvidia-smi
# nvidia-docker run nvidia/cuda:9.0-base nvidia-smi
または (以下の方法は Docker バージョン 19.03 およびそれ以降が必要です):
# docker run --gpus all nvidia/cuda:9.0-base nvidia-smi
CUDA 付き Arch Linux イメージ
以下の Dockerfile
を使うことで、CUDA 付きのカスタム Arch Linux イメージをビルドできます。ホスト上で pacman パッケージをキャッシュするために Dockerfile frontend syntax 1.2 を使用します。Docker イメージをビルドする前に、クライアント上で DOCKER_BUILDKIT=1
環境変数を設定する必要があります。
Dockerfile
# syntax = docker/dockerfile:1.2 FROM archlinux # install packages RUN --mount=type=cache,sharing=locked,target=/var/cache/pacman \ pacman -Syu --noconfirm --needed base base-devel cuda # configure nvidia container runtime # https://github.com/NVIDIA/nvidia-container-runtime#environment-variables-oci-spec ENV NVIDIA_VISIBLE_DEVICES all ENV NVIDIA_DRIVER_CAPABILITIES compute,utility
便利なヒント
実行中のコンテナの IP アドレスを取得するには:
$ docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' <container-name OR id>
172.17.0.37
それぞれの実行中のコンテナについて、/etc/hosts
で使うために名前と対応する IP アドレスを出力:
#!/usr/bin/env sh for ID in $(docker ps -q | awk '{print $1}'); do IP=$(docker inspect --format="{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}" "$ID") NAME=$(docker ps | grep "$ID" | awk '{print $NF}') printf "%s %s\n" "$IP" "$NAME" done
クロスコンパイルに buildx を使う
Docker バージョン 19.03 から [8]、Docker パッケージには、新しい BuildKit building toolkit (日本語訳ページ) を使う buildx CLI プラグインが含まれています。buildx インターフェイスはマルチプラットフォームなイメージのビルドをサポートしています (ホストのアーキテクチャ以外も)。
イメージのクロスコンパイルには QEMU が必要です。Docker 内で QEMU の静的ビルドをセットアップする方法については、multiarch/qemu-user-static イメージの情報を見てください。あるいは、QEMU をホストのシステム上でセットアップして、Docker と一緒に使う方法については、QEMU#x86_64 から arm/arm64 環境への chrooting を見てください。どちらの場合にせよ、あなたのシステムはゲストアーキテクチャのユーザモードエミュレート用に設定されます。
$ docker buildx ls NAME/NODE DRIVER/ENDPOINT STATUS PLATFORMS default * docker default default running linux/amd64, linux/386, linux/arm64, linux/riscv64, linux/s390x, linux/arm/v7, linux/arm/v6
Docker とイメージの削除
Docker を完全に削除したい場合は以下の手順に従ってください。
実行中のコンテナをチェックする:
# docker ps
削除するために、ホスト上で実行中のコンテナをすべて表示する:
# docker ps -a
実行中のコンテナを停止する:
# docker stop <CONTAINER ID>
依然として実行中のコンテナを kill する:
# docker kill <CONTAINER ID>
ID でリストされたコンテナを削除する:
# docker rm <CONTAINER ID>
Docker イメージをすべて表示する:
# docker images
ID でイメージを削除する:
# docker rmi <IMAGE ID>
コンテナに関連付けられていない (ダングリング) すべてのイメージ、コンテナ、ボリューム、ネットワークを削除する:
# docker system prune
停止中のコンテナと未使用のイメージ (ダングリングイメージでないもの) を追加で削除するには、-a フラグをコマンドに追加してください:
# docker system prune -a
すべての Docker データを削除する (ディレクトリを削除する):
# rm -R /var/lib/docker
トラブルシューティング
Btrfs ファイルシステムで Docker イメージを消去
btrfs ファイルシステムで docker イメージを削除すると /var/lib/docker/btrfs/subvolumes/
にサイズが0のイメージが残されてしまいます。これを削除しようとするとパーミッションエラーが表示されます:
# docker rm bab4ff309870 # rm -Rf /var/lib/docker/btrfs/subvolumes/* rm: cannot remove '/var/lib/docker/btrfs/subvolumes/85122f1472a76b7519ed0095637d8501f1d456787be1a87f2e9e02792c4200ab': Operation not permitted
このエラーは btrfs が docker イメージのためにサブボリュームを作成したのが原因です。したがって削除するときの正しいコマンドは次のようになります:
# btrfs subvolume delete /var/lib/docker/btrfs/subvolumes/85122f1472a76b7519ed0095637d8501f1d456787be1a87f2e9e02792c4200ab
docker0 ブリッジが IP を取得できない / コンテナからインターネットにアクセスできない
Docker は自分で IP フォワーディングを有効にしますが、デフォルトでは systemd-networkd によって sysctl の設定が上書きされてしまいます。ネットワークプロファイルに IPForward=yes
を設定してください。詳しくはインターネット共有#パケット転送の有効化を参照してください。
デフォルトで使用できるプロセスやスレッドの数が少なすぎる
以下のようなエラーメッセージが表示される場合:
# e.g. Java java.lang.OutOfMemoryError: unable to create new native thread # e.g. C, bash, ... fork failed: Resource temporarily unavailable
systemd によって許可されるプロセスの数を調整する必要があります。デフォルトは 500 ですが (system.conf
を参照)、複数の docker コンテナを動作させるには少なすぎます。以下のスニペットで docker.service
を編集してください:
# systemctl edit docker.service
[Service] TasksMax=infinity
Error initializing graphdriver: devmapper
systemctl で docker の起動に失敗して以下のエラーが表示される場合:
Error starting daemon: error initializing graphdriver: devmapper: Device docker-8:2-915035-pool is not a thin pool
エラーを解消するには、サービスを停止して、/var/lib/docker/
を (必要に応じて) バックアップし、/var/lib/docker/
の中身を消してから、サービスを起動してみてください。詳しくは GitHub issue を参照。
Failed to create some/path/to/file: No space left on device
以下のようにエラーメッセージが表示される場合:
ERROR: Failed to create some/path/to/file: No space left on device
Docker イメージの作成・実行時、ディスク容量が十分に存在するにもかかわらず、上記のメッセージが表示されるときは以下を確認してください:
- Tmpfs が無効になっている、あるいは十分なメモリが割り当てられている。Docker が
/tmp
にファイルを書き出そうとしていて、ディスク容量ではなくメモリ使用量が制限となっている可能性があります。 - XFS を使っている場合、
/etc/fstab
の (/tmp
や/var/lib/docker
がある) エントリからnoquota
マウントオプションを削除すると良いかもしれません。詳しくはディスククォータを参照してください。Docker ストレージドライバーのoverlay2
を使用するときは特に注意してください。 - XFS クォータのマウントオプション (
uquota
,gquota
,prjquota
など) がファイルシステムの再マウント時に失敗している。ルートファイルシステムでクォータを使うには、マウントオプションをrootflags=
カーネルパラメータで initramfs に渡す必要があります。その場合、root (/
) ファイルシステムのマウントオプションとして/etc/fstab
に指定してはいけません。
カーネル 4.19.1 で Invalid cross-device link
docker 内で 'dpkg' のようなコマンドの実行に失敗することがあります。例:
dpkg: error: error creating new backup file '/var/lib/dpkg/status-old': Invalid cross-device link
その場合 overlay.metacopy=N
カーネルパラメータを追加するか、この問題 が解決するまで 4.18.x にダウングレードしてください。詳しくは Arch フォーラム を参照。
virtualbox ドライバーを使用したときに Docker-machine が仮想マシンの作成に失敗する
以下のように virtualbox ドライバーで docker-machine が仮想マシンの作成に失敗する場合:
VBoxManage: error: VBoxNetAdpCtl: Error while adding new interface: failed to open /dev/vboxnetctl: No such file or directory
vboxreload
で CLI から virtualbox をリロードしてください。
Docker を起動すると KVM のブリッジネットワークが壊れる
既知のバグ が原因です。以下の方法で回避できます:
/etc/docker/daemon.json
{ "iptables": false }