それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

LXC 内部で docker を動かす。 ( docker in LXC container )

LXC 内部で docker を動かす。

既知の問題点 lxc 内部で docker は動かない ことがある

調べた結果、次の条件で動かない。

  • docker のoverlay2 が lxc デフォルトzfs で動かない
  • docker のoverlayがありlxc 内部でsnapcraft-docker を使うと動かない。
  • docker の権限管理がLXC のデフォルトで動かない。

今の処分っている問題点は、overlay2 の関するものなので、zfs を避けると動く

ただし、snapcraft で docker を入れると動かない。 snap でインストールされる docker のバージョンの問題なのか、 snap が管理するストレージがネストしててやばいのか。

そのへんはまだよくわかってない

ということで docker in LXC のポイント

  • snapcraft の docker は動かない
  • lxc の特権コンテナが必要
  • LXCストレージでZFSでDockerは動かない

このポイントをクリアすると動作しました。

こうすればひとまず動く

btrfs のストレージを作る。

lxc storage create bt01 btrfs

docker を動かすLXCコンテナを ubuntu のLTSから作る

lxc launch ubuntu:20.04 docker-host --storage bt01

LXCのコンテナに対していくつかの権限設定をする。

lxc config set docker-host security.privileged true
lxc config set docker-host security.nesting true

新しい権限で、LXC コンテナを起動し直す。

lxc restart docker-host

Ubuntu LTS のコンテナに対して apt 更新を掛ける。

lxc exec docker-host apt update 
lxc exec docker-host apt upgrade  

これでbtrfs で作ったストレージにコンテナを立ち上げたので、その内部で docker をインストールしてみる

lxc exec docker-host apt install docker.io

インストールした docker で hello-world をしてみる。

lxc exec docker-host docker run hello-world

やったね、無事にrun docker in LXC container ができたよ。

docker run hello-world を試す。

lxc exec 経由で docker run を試す。

lxc exec docker-host docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
0e03bdcc26d7: Pull complete
Digest: sha256:d58e752213a51785838f9eed2b7a498ffa1cb3aa7f946dda11af39286c3db9a9
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/

For more examples and ideas, visit:
https://docs.docker.com/get-started/

無事に動いたときの設定などをメモっておく

LXC ホスト

takuya@:~$ lsb_release -a
No LSB modules are available.
Distributor ID:    Ubuntu
Description:    Ubuntu 20.04 LTS
Release:    20.04
Codename:    focal

LXD バージョン

takuya@:~$ lxc version
Client version: 4.3
Server version: 4.3

LXC コンテナ

takuya@:~$ lxc exec docker-host -- lsb_release -a
No LSB modules are available.
Distributor ID:    Ubuntu
Description:    Ubuntu 20.04 LTS
Release:    20.04
Codename:    focal

Docker バージョン

takuya@:~$ lxc exec docker-host docker version
Client:
Version:           19.03.8
API version:       1.40
Go version:        go1.13.8
Git commit:        afacb8b7f0
Built:             Tue Jun 23 22:26:12 2020
OS/Arch:           linux/amd64
Experimental:      false

Server:
Engine:
  Version:          19.03.8
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.13.8
  Git commit:       afacb8b7f0
  Built:            Thu Jun 18 08:26:54 2020
  OS/Arch:          linux/amd64
  Experimental:     false
containerd:
  Version:          1.3.3-0ubuntu2
  GitCommit:
runc:
  Version:          spec: 1.0.1-dev
  GitCommit:
docker-init:
  Version:          0.18.0
  GitCommit:

2023-10-06 追記

docker compose で mailcow を上記の状態で up down したら

などとなり、OS起動時は動くのに、docker 側で down -> up するとエラーになった。

Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error setting cgroup config for procHooks process: failed to write "a *:* rwm": write /sys/fs/cgroup/devices/docker/3cf0487fa80fd2a06f4a61b7c5ae58231db463e2a922bd28ca4a7abb00247b18/devices.allow: operation not permitted: unknown

なんとなく、以前のdocker on lxc で使っていた raw.lxc を書き直したらエラーが出なくなった。

  raw.lxc: |-
    lxc.mount.auto=proc:rw sys:rw cgroup:rw
    lxc.cgroup.devices.allow=a
    lxc.cap.drop=

ailed to write "a : rwm": write /sys/fs/cgroup/devices/docker

devices.allow … operation not permitted` in privileged container

Cannot start hello-world in LXC conatiner

なんでLXCコンテナの中でDockerを動かすのか。

特に理由はない。なんか面白そうだから。

強いてあげるなら、docker / docker-compose したコンテナを長期間動かすと、メンテがめんどくさいから。

docker/docker-compose を使ってると、コンテナが増えすぎてどのコンテナがどのサービス用なのかゴチャゴチャになってわからなくなる。巷ではdocker の管理UIをdocker run すとかもあるみたいだけど、それもなんか違う気がするし、docker のコンテナとボリュームが稼働しているマシンを別のマシンに移動させたり、バックアップを取得したり、そういう管理が本当にめんどくさい。

docker ってパパっとインスタンスを立ち上げて使い捨てるには本当に便利なんだけど、長期間動かすのには向いてない気がする。ちょっとパフォーマンスが足りないからCPUやメモリを潤沢にした新サーバーに移動しようとか、さくらのVPSの別の契約に移動しようとか、そういうことをやろうとして本当に苦労した。なのでdocker を、LXCとかlibvirt+kvm に閉じ込めておくほうがライブマイグレーションができて便利だと思った次第。

docker は開発用に実験環境を作るのは本当にすばらしい。docker でインスタンスをサクッと立ち上げるのもスラバシイし、デプロイ時にデータボリュームとソースコードの領域を分けられるのも素晴らしいと思うんだけど、データボリュームをいちいち移動するのとか、デプロイ設定を書き換えるのが面倒じゃないですかね。まぁGoogleAmazonを使えばいいんだろうけど。

LXC/LXDとかsystemd-nspawn とか名前空間を使った実行に docker が対応すべきだと思います。はい。個人的な意見ですけど。

個人的な意見ですけど、docker はソフトウェア開発の環境にすごく向いている。LXC はサーバーの実験環境をつくるのにすごく向いている。と思います。

そもそも docker run したインスタンスを長期間運用するとなると、バージョンアップとかコンテナのベースになってるイメージの更新とかあるので、dockerfile だとか docker-compose をよーく読んでvolume をよく考えないといけない。その作業がもうめんどくさい。

nextcloud や mattermost や gitlab をdocker で起動して痛い目にあった