Docker

提供: ArchWiki
2022年9月24日 (土) 07:11時点におけるAshMyzk (トーク | 投稿記録)による版 (→‎クロスコンパイルに buildx を使う: 追加)
ナビゲーションに移動 検索に移動

関連記事

Docker は軽量コンテナとしてあらゆるアプリケーションを詰めて運んで実行できるユーティリティです。

ノート: 訳注: この記事では、https://docs.docker.com の日本語訳ページとして https://docs.docker.jp のページも合わせて表示しています。Docker ドキュメントの日本語訳プロジェクトについては https://docs.docker.jp/about.html を見てください。

インストール

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 グループに追加することは、そのユーザーを root にするのと等価です。なぜなら、そのグループに属するユーザーは docker run --privileged コマンドを実行して、コンテナを root 権限で開始することができるからです。詳しくは こちらこちら (日本語訳ページ) を参照してください。

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 (日本語訳ページ) を見てください。

設定

ストレージドライバー

docker のストレージドライバー (グラフドライバー) は性能に大きな影響を与えます。ストレージドライバーはコンテナのイメージレイヤーを効率的に保存し、複数のイメージでレイヤーを共有している場合、ディスク容量を使用するレイヤーはひとつだけになります。デフォルトのストレージドライバーである devicemapper は次善的な性能しか発揮できず、ハードディスクでは問題外です。したがって、プロダクション環境で devicemapper を使用することは推奨されません。

Arch Linux のカーネルは新しいため、古いドライバーを使用する意味はありません。overlay2 が新しいドライバーです。

現在のストレージドライバーを確認するには # docker info | grep "Storage Driver" を実行してください。最近の docker 環境では overlay2 がデフォルトで使われます。

ストレージドライバーを自分で選択して設定するには、/etc/docker/daemon.json を編集してください (ファイルが存在しない場合は作成してください):

/etc/docker/daemon.json
{
  "storage-driver": "overlay2"
}

その後、docker を再起動してください。

オプションに関する詳細は ユーザーガイド を見てください。daemon.json の中のオプションの詳細は dockerd のドキュメント を見てください。

Remote API

ポート 4243 で Remote API を手動で開くには:

# /usr/bin/dockerd -H tcp://0.0.0.0:4243 -H unix:///var/run/docker.sock

-H tcp://0.0.0.0:4243 で Remote API が開かれます。

-H unix:///var/run/docker.sock はターミナルからホストマシンにアクセスできるようにします。

Remote API と systemd

docker デーモンで Remote API を起動するには、以下の内容でドロップインスニペットを作成してください:

/etc/systemd/system/docker.service.d/override.conf
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:4243 -H unix:///var/run/docker.sock

デーモンのソケットの設定

docker デーモンはデフォルトで Unix ソケットを使います。特定のポートを listen させるには、以下の内容のドロップインスニペットを作成してください:

/etc/systemd/system/docker.socket.d/socket.conf
[Socket]
ListenStream=0.0.0.0:2375

プロキシ

プロキシの設定は2つに分けられます。ひとつは Docker デーモンのホストの設定で、もうひとつはコンテナからプロキシにアクセスできるようにするための設定です。

プロキシの設定

以下の内容でドロップインスニペットを作成:

/etc/systemd/system/docker.service.d/proxy.conf
[Service]
Environment="HTTP_PROXY=192.168.1.1:8080"
Environment="HTTPS_PROXY=192.168.1.1:8080"
ノート: これはあなたのプロクシサーバが 192.168.1.1 だと仮定しています、127.0.0.1 は使わないでください。

設定がロードされたことを確認:

# systemctl show docker --property Environment
Environment=HTTP_PROXY=192.168.1.1:8080 HTTPS_PROXY=192.168.1.1:8080

コンテナの設定

docker.service ファイルの設定はコンテナには適用されません。DockerfileENV 変数を設定する必要があります:

FROM base/archlinux
ENV http_proxy="http://192.168.1.1:3128"
ENV https_proxy="https://192.168.1.1:3128"

Docker は Dockerfile で ENV を使って設定する方法について詳しい情報を提供しています。

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 は非特権ユーザ名前空間の利用 (CONFIG_USER_NS_UNPRIVILEGED) に依存しており、これはセキュリティ上、重要な意味を持ちます。詳細については、セキュリティ#アプリケーションのサンドボックス化 をご覧ください

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

パッケージ devtoolsfakechrootfakeroot はインストールされていることに注意してください。

ベースイメージをビルドするには:

$ 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 を使用する他のシステム) 上で実行すると、バグとパフォーマンス上の問題を生じる場合があります。例は、[4][5][6] を見てください。

CentOS

次のコマンドは最新の centos イメージを pull します:

# docker pull centos

各 CentOS リリースで利用可能なタグの完全なリストは Docker Hub ページを見てください。

Debian

次のコマンドは最新の debian イメージを pull します:

# docker pull debian

(各 Debian リリースの標準バージョンとスリムバージョンの療法を含む) 利用可能なタグの完全なリストは Docker Hub ページを見てください。

Distroless

Google は、パッケージマネージャやシェルなどの OS コンポーネントの無い最小イメージである distroless イメージをメンテナンスしています。これにより、ソフトウェアをパッケージングするためにイメージのサイズを非常に小さくできます。

イメージのリストと様々なプログラミング言語での使用法に関する指示は GitHub README を見てください。

便利なヒント

実行中のコンテナの 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 から [7]、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

トラブルシューティング

systemd 232 でコンテナが起動できない

カーネルパラメータとして systemd.legacy_systemd_cgroup_controller=yes を追加してください。詳しくは バグレポート を参照。

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 を設定してください。詳しくはインターネット共有#パケット転送の有効化を参照してください。

ノート:
  • systemd-networkd.serviceiptables.service再起動したときは docker.service再起動する必要があります。
  • nftables によって docker の接続がデフォルトでブロックされる可能性があります。nft list ruleset を使ってブロックしているルールを確認してください。nft flush chain inet filter forward で一時的に全ての転送ルールを削除できます。変更を永続化するには /etc/nftables.conf を編集してください。設定ファイルからルールをリロードするには nftables.service再起動してください。

デフォルトで使用できるプロセスやスレッドの数が少なすぎる

以下のようなエラーメッセージが表示される場合:

# 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 に指定してはいけません。
ノート: XFS のクォータと Linux 標準のディスククォータには違いが存在します。詳しくは [8] を参照してください。

カーネル 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
}

参照