====== Docker ======
===== Docker =====
==== install ====
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install docker-ce
| ''docker run'' | ''-it'' | |
==== イメージ ====
=== イメージ名,タグの変更 ===
* docker tag old_name:tag new_name:tag 元のイメージは消去されない.
=== イメージ 書き出し/読み込み ===
gzip 使うとき
docker save hoge/fuga:piyo > hoge_fuga_piyo.tar
docker load < hoge_fuga_piyo.tar
gzip 使わないとき
docker save hoge/fuga:piyo | gzip -c > hoge_fuga_piyo.tar.gz
docker load < hoge_fuga_piyo.tar.gz
=== dangling なイメージの削除 ===
最近は複雑なフィルタやコマンドライン変数など使わずにできるようになった。
docker image prune
==== volume ====
=== 無名 volume の確認 ===
docker volume ls
DRIVER VOLUME NAME
local 63a68bdc4cd34a2d378502716f9e3582bc3cc2432581470c8077a67773b778b0
local 676245ef8581ad1a2b3481628f6e097d7371ed076b47d02d8d9d70d8bc6a8994
ボリュームの詳細な情報を知ることができる。
docker volume inspect 63a68bdc4cd34a2d378502716f9e3582bc3cc2432581470c8077a67773b778b0
どのコンテナから参照されている volume なのかは各コンテナの詳細情報から調べるしか無い。
以下のようにすればどこにマウントされていたかわかる
docker inspect コンテナID | grep 63a68bdc4cd34a2d378502716f9e3582bc3cc2432581470c8077a67773b778b0
何からも参照されていないもの
docker volume ls -f dangling=true
削除
docker volume rm 63a68bdc4cd34a2d378502716f9e3582bc3cc2432581470c8077a67773b778b0
=== Dockerfile で sudo 可能ユーザーを作る ===
ARG GID=1111
ARG UID=1111
ARG CONTAINER_USERNAME=sdwebui
ARG PASSWORD=sdwebui
RUN groupadd -g ${GID} ${CONTAINER_USERNAME} \
&& useradd -m -s /bin/bash -u ${UID} -g ${GID} -G sudo ${CONTAINER_USERNAME} \
&& echo "${PASSWORD}\n${PASSWORD}\n" | passwd ${CONTAINER_USERNAME} \
&& echo "Defaults visiblepw" >> /etc/sudoers \
&& echo "${CONTAINER_USERNAME} ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
USER ${UID}:${GID}
=== 稼働中コンテナに入る ===
ログイン(login) する。
docker exec -it CONTAINER_ID /bin/bash
==== rootless Docker ====
=== イメージ保存場所の変更 ===
''~/.config/docker/daemon.json'' を変更するべし。 rootfull ならたぶん ''/etc/docker/daemon.json''
v23未満
{
"graph": "/mnt/extra/docker"
}
v23以降
{
"data-root": "/mnt/extra/docker"
}
編集したら設定を反映。
systemctl --user restart docker
docker info | grep "Docker Root Dir" で確認。
''/home/USER/.local/share/docker'' から切り替わっていたらOK。
===== docker-compose =====
=== yaml ファイルの検証 ===
''docker compose config''
===== podman =====
podman は docker(moby) みたいにコンテナ動かすやつ。dockerコマンドを単純に podman に置き換えるだけで使えるようにしているっぽい。
docker よりも優れた点がいくつかある。
rootless docker を使う上で問題となる bind マウントのユーザーの所有権問題などがうまく解決されている?
==== インストール ====
管理者権限で podman をインストールすると、全ユーザーが使えるようになる。\\
基本的には普通に使うと rootless モードで実行される。docker みたいに裏で daemon が走っていたりはしない。
=== リポジトリ追加 ===
ubuntu18.04, 20.04 はデフォルトではリポジトリがない(公式にはサポート対象外)。
. /etc/os-release
echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_${VERSION_ID}/ /" \
| sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_${VERSION_ID}/Release.key \
| sudo apt-key add -
=== インストール ===
sudo apt update
sudo apt install podman
ubuntu 18.04, 20.04 では少し古いバージョンがインストールされる。
20.04 だとミラーサーバーが壊れてて .deb ファイルがうまくダウンロードされないことがある。
=== GPUを使用する場合 ===
ランタイムをインストールして設定ファイルを一部変更する。
sudo apt install nvidia-container-runtime
''/etc/nvidia-container-runtime/config.toml'' を一行だけ修正。
sudo vim /etc/nvidia-container-runtime/config.toml
no-cgroups = true
**ubuntuのみ追加でやらないといけないこと** \\
''nvidia-container-runtime'' をインストールしたときには
''/usr/share/containers/oci/hooks.d/oci-nvidia-hook.json'' が自動生成されるはずだが、
Ubuntu 環境ではうまくいっていないみたい。( [[https://github.com/NVIDIA/nvidia-container-toolkit/issues/17|参考]] )
なので以下のように自分で作成する。
sudo mkdir -p /usr/share/containers/oci/hooks.d/
sudo vim /usr/share/containers/oci/hooks.d/oci-nvidia-hook.json
{
"version": "1.0.0",
"hook": {
"path": "/usr/bin/nvidia-container-toolkit",
"args": ["nvidia-container-toolkit", "prestart"],
"env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
]
},
"when": {
"always": true,
"commands": [".*"]
},
"stages": ["prestart"]
}
==== 使用 ====
基本的には docker コマンドを単純に podman に置き換えるだけ。\\
デフォルトでは rootless モードで起動される。
=== GPUを使用する場合 ===
podman run -it --rm --security-opt=label=disable \
--hooks-dir=/usr/share/containers/oci/hooks.d/ \
-v /home/horiuchi/work/tmp:/workdir \
-w /workdir nvidia/cuda:11.3.1-cudnn8-devel-ubuntu20.04 /bin/bash
''--security-opt=label=disable'' と ''--hooks-dir=/usr/share/containers/oci/hooks.d/'' が必要無さそう?
nvidia イメージを使うと自動的に hooks を見てくれるっぽい。
=== rootlessモードでコンテナ内の特定のユーザーになる ===
例えば外で ''UID=3333'' 、コンテナ内で ''UID=4444'' になりたい場合、
uidmap の設定をちゃんとしないと bind マウントした volume がコンテナ内で root の所有となるため、
コンテナ内の ''4444'' ユーザーからアクセスできない。
以下のように起動する。''%%-%%-uidmap'' オプションを二回入れないといけないところが重要。
podman run -it --rm --uidmap 0:1:4444 --uidmap 4444:0:1 \
-v /home/horiuchi/tmp:/workdir \
-w /workdir docker.io/library/ubuntu:20.04 /bin/bash
nvidia のランタイムでは uidmap が効かずに落ちる...(2022/12/06)
本来的には ''/etc/subuid'' を参考にもうひとつ ''%%-%%-uidmap'' をする必要がある。
例 ''%%-%%-uidmap 4445:4445:61092'' (4444+1, 4444+1, 65536-4444, 65536は''/etc/subuid''の3番目の項目)
==== podman で docker-compose を使う ====
podman のデーモンの起動が必要。これでソケットを作って docker の代わりに使えるようにする。
systemctl --user enable --now podman.socket
export DOCKER_HOST=unix:///run/user/1705/podman//podman.sock
==== VSCode Devcontainer を podman で利用する ====
''devcontainer.json'' で userns 設定をするっぽい。
もしかしたら nvidia と一緒にはできないかも。
===== DevContainer =====
gitリポジトリにおいて、①VSCodeとdevcontainerで環境を使う場合、②docker-composeだけで環境を使用する場合、の2つのやり方を実現したい。
以下のようなディレクトリ構成にするのが良い。
- /
- docker-compose.yaml
- Makefile
- .devcontainer/
- devcontainer.json
- docker-compose.yaml : devcontainer特有のcompose設定
''devcontainer.json'' には次のように書けば良い。
{
"dockerComposeFile": ["../docker-compose.yaml", "docker-compose.yaml"],
"service": "CONTAINER_SERVICE_NAME",
"workspaceFolder": "/workspaces/GIT_REPOSITORY_NAME",
"postStartCommand": "git config --global --add safe.directory ${containerWorkspaceFolder}",
}
=== tips: composeのオーバーライド ===
''docker-compose.override.yaml'' というファイルを作ると自動的にオーバーライドするような仕組みが存在している(ドキュメントには書かれていない?)
composeファイルを結合するとき、同名の辞書があると要素を追加するような形で結合される。つまり、すでにあった要素は消されない。
明示的に消したい場合、たとえば ports: !reset[] と書くことで消去することができるらしい。