広告 デバイス

【解説】Raspberry Pi+Dockerでサーバ構築

※本ページには、プロモーション(広告)が含まれています。

悩んでいる人

Raspberry PiでDockerを動かしたい。環境構築方法を教えて欲しい。

また、活用事例とともに具体的なサーバ構築方法を教えて欲しい。

こんなお悩みを解決します。

今回から、Raspberry Piを用いて、下記のアプリケーションを構築し、LAN内で小型サーバとして運用していきます。

  • Webサーバ
  • 赤外線制御サーバ
  • NAS

まだ、Raspberry Piを購入していない方は、以下の記事を参考にしてください。

あわせて読みたい
【紹介】Raspberry Piの活用事例

続きを見る

全体構成

最初にDocker環境で構築するシステムの全体像を定義しておきます。ただ、使いやすさの関係を考慮して今後変更する可能性もあります。

コンテナ構成

同じ色の線は、同じネットワークを表し、黒色の線はホスト側のデバイスとつながることを意味します。

また、それぞれの枠はコンテナを用いて実現します。

今回の場合、以下の5つのコンテナが出来上がることになります。

  • NAS(Samba)
  • Web Server(Node.js)
  • DataBase(MariaDB)
  • Web Server(NodeRed)
  • Infrared Contoroller

Infrared Contorollerは、Alpineベースで環境を構築し、pythonのプログラムを常時実行する予定です。

Docker環境の導入

まずは、Docker環境を導入していきます。

以前の投稿を参考にしながら、Raspberry PiにSSHします。

あわせて読みたい
【解説】Raspberry Piの初期設定(SSH接続・OSアップデート)

続きを見る

Dockerのインストール

SSH後に、以下のコマンドを実行します。

# =====
# 準備
# =====
sudo apt update
# python3のインストール
sudo apt -y install python3-dev python3-pip
# dbus-user-sessionのインストール
sudo apt-get install -y dbus-user-session
# fuse-overlayfsのインストール
sudo apt-get install -y fuse-overlayfs
# slirp4netnsのインストール
sudo apt-get install -y slirp4netns
# uidmapとiptablesのインストール
sudo apt-get install -y uidmap iptables

# =====================
# Dockerのインストール
# =====================
curl -fsSL https://get.docker.com/rootless | sh

Dockerをインストールすると以下のようなメッセージが表示されます。

curl -fsSL https://get.docker.com/rootless | sh
# Installing stable version 20.10.14
# Executing docker rootless install script, commit: 0221ade
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 55.1M  100 55.1M    0     0  9349k      0  0:00:06  0:00:06 --:--:-- 10.0M
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 19.7M  100 19.7M    0     0   9.9M      0  0:00:01  0:00:01 --:--:--  9.9M
+ PATH=/home/user/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games /home/user/bin/dockerd-rootless-setuptool.sh install
[INFO] Creating /home/user/.config/systemd/user/docker.service
[INFO] starting systemd service docker.service
+ systemctl --user start docker.service
+ sleep 3
+ systemctl --user --no-pager --full status docker.service
● docker.service - Docker Application Container Engine (Rootless)
     Loaded: loaded (/home/user/.config/systemd/user/docker.service; disabled; vendor preset: enabled)
     Active: active (running) since Fri 2022-04-29 01:25:49 JST; 3s ago
       Docs: https://docs.docker.com/go/rootless/
   Main PID: 2018 (rootlesskit)
      Tasks: 36
        CPU: 1.125s
     CGroup: /user.slice/user-1000.slice/user@1000.service/app.slice/docker.service
             tq2018 rootlesskit --net=slirp4netns --mtu=65520 --slirp4netns-sandbox=auto --slirp4netns-seccomp=auto --disable-host-loopback --port-driver=builtin --copy-up=/etc --copy-up=/run --propagation=rslave /home/user/bin/dockerd-rootless.sh
             tq2028 /proc/self/exe --net=slirp4netns --mtu=65520 --slirp4netns-sandbox=auto --slirp4netns-seccomp=auto --disable-host-loopback --port-driver=builtin --copy-up=/etc --copy-up=/run --propagation=rslave /home/user/bin/dockerd-rootless.sh
             tq2048 slirp4netns --mtu 65520 -r 3 --disable-host-loopback --enable-sandbox --enable-seccomp 2028 tap0
             tq2057 dockerd
             mq2084 containerd --config /run/user/1000/docker/containerd/containerd.toml --log-level info
 4月 29 01:25:50 raspberrypi dockerd-rootless.sh[2084]: time="2022-04-29T01:25:50.447355395+09:00" level=info msg="loading plugin \"io.containerd.content.v1.content\"..." type=io.containerd.content.v1
 4月 29 01:25:50 raspberrypi dockerd-rootless.sh[2084]: time="2022-04-29T01:25:50.449342408+09:00" level=info msg="loading plugin \"io.containerd.snapshotter.v1.aufs\"..." type=io.containerd.snapshotter.v1
 4月 29 01:25:50 raspberrypi dockerd-rootless.sh[2084]: time="2022-04-29T01:25:50.460375375+09:00" level=info msg="skip loading plugin \"io.containerd.snapshotter.v1.aufs\"..." error="aufs is not supported (modprobe aufs failed: exit status 1 \"modprobe: FATAL: Module aufs not found in directory /lib/modules/5.15.32-v8+\\n\"): skip plugin" type=io.containerd.snapshotter.v1
 4月 29 01:25:50 raspberrypi dockerd-rootless.sh[2084]: time="2022-04-29T01:25:50.460670504+09:00" level=info msg="loading plugin \"io.containerd.snapshotter.v1.btrfs\"..." type=io.containerd.snapshotter.v1
 4月 29 01:25:50 raspberrypi dockerd-rootless.sh[2084]: time="2022-04-29T01:25:50.462004648+09:00" level=info msg="skip loading plugin \"io.containerd.snapshotter.v1.btrfs\"..." error="path /home/user/.local/share/docker/containerd/daemon/io.containerd.snapshotter.v1.btrfs (ext4) must be a btrfs filesystem to be used with the btrfs snapshotter: skip plugin" type=io.containerd.snapshotter.v1
 4月 29 01:25:50 raspberrypi dockerd-rootless.sh[2084]: time="2022-04-29T01:25:50.462288888+09:00" level=info msg="loading plugin \"io.containerd.snapshotter.v1.devmapper\"..." type=io.containerd.snapshotter.v1
 4月 29 01:25:50 raspberrypi dockerd-rootless.sh[2084]: time="2022-04-29T01:25:50.462503369+09:00" level=warning msg="failed to load plugin io.containerd.snapshotter.v1.devmapper" error="devmapper not configured"
 4月 29 01:25:50 raspberrypi dockerd-rootless.sh[2084]: time="2022-04-29T01:25:50.462610554+09:00" level=info msg="loading plugin \"io.containerd.snapshotter.v1.native\"..." type=io.containerd.snapshotter.v1
 4月 29 01:25:50 raspberrypi dockerd-rootless.sh[2084]: time="2022-04-29T01:25:50.463378311+09:00" level=info msg="loading plugin \"io.containerd.snapshotter.v1.overlayfs\"..." type=io.containerd.snapshotter.v1
 4月 29 01:25:51 raspberrypi dockerd-rootless.sh[2057]: time="2022-04-29T01:25:51.174232304+09:00" level=warning msg="grpc: addrConn.createTransport failed to connect to {unix:///run/user/1000/docker/containerd/containerd.sock   0 }. Err :connection error: desc = \"transport: error while dialing: dial unix:///run/user/1000/docker/containerd/containerd.sock: timeout\". Reconnecting..." module=grpc
 4月 29 01:25:53 raspberrypi dockerd-rootless.sh[2057]: time="2022-04-29T01:25:53.632843052+09:00" level=warning msg="grpc: addrConn.createTransport failed to connect to {unix:///run/user/1000/docker/containerd/containerd.sock   0 }. Err :connection error: desc = \"transport: error while dialing: dial unix:///run/user/1000/docker/containerd/containerd.sock: timeout\". Reconnecting..." module=grpc
+ DOCKER_HOST=unix:///run/user/1000/docker.sock /home/user/bin/docker version
Client:
 Version:           20.10.14
 API version:       1.41
 Go version:        go1.16.15
 Git commit:        a224086
 Built:             Thu Mar 24 01:44:53 2022
 OS/Arch:           linux/arm64
 Context:           default
 Experimental:      true
Server: Docker Engine - Community
 Engine:
  Version:          20.10.14
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.16.15
  Git commit:       87a90dc
  Built:            Thu Mar 24 01:48:38 2022
  OS/Arch:          linux/arm64
  Experimental:     false
 containerd:
  Version:          v1.5.11
  GitCommit:        3df54a852345ae127d1fa3092b95168e4a88e2f8
 runc:
  Version:          1.0.3
  GitCommit:        v1.0.3-0-gf46b6ba2
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0
+ systemctl --user enable docker.service
Created symlink /home/user/.config/systemd/user/default.target.wants/docker.service → /home/user/.config/systemd/user/docker.service.
[INFO] Installed docker.service successfully.
[INFO] To control docker.service, run: `systemctl --user (start|stop|restart) docker.service`
[INFO] To run docker.service on system startup, run: `sudo loginctl enable-linger user`
[INFO] Creating CLI context "rootless"
Successfully created context "rootless"
[INFO] Make sure the following environment variables are set (or add them to ~/.bashrc):
export PATH=/home/user/bin:$PATH
export DOCKER_HOST=unix:///run/user/1000/docker.sock

最後に、INFOとして以下の事が取り上げられているので、対応します。

  1. To run docker.service on system startup, run: `sudo loginctl enable-linger user`
    sudo loginctl enable-linger userを実行
  2. ~/.bashrcに以下の環境変数を追加
    • export PATH=/home/user/bin:${PATH}
    • export DOCKER_HOST=unix:///run/user/1000/docker.sock

ここで、/home/user/run/user/1000の「user」や「1000」は実行する環境によって変化します。ご自身の環境に合わせて設定してください。

私の環境の場合、~/.bashrcは以下のようになります。変更箇所は、11行目~13行目になります。

~/.bashrcの更新

最後に、再起動します。再起動後、以下のコマンドを実行します。

# dockerサービスの状態を確認
systemctl --user status docker

コマンドを実行すると、以下のようなメッセージが表示されます。

systemctl --user status docker
● docker.service - Docker Application Container Engine (Rootless)
     Loaded: loaded (/home/user/.config/systemd/user/docker.service; enabled; vendor preset: enabled)
     Active: active (running) since Fri 2022-04-29 01:49:28 JST; 2min 30s ago
       Docs: https://docs.docker.com/go/rootless/
   Main PID: 558 (rootlesskit)
      Tasks: 39
        CPU: 2.566s
     CGroup: /user.slice/user-1000.slice/user@1000.service/app.slice/docker.service
             tq558 rootlesskit --net=slirp4netns --mtu=65520 --slirp4netns-sandbox=auto --slirp4netns-seccomp=auto --disable-host-loopback --port-driver=builtin --copy-up=/etc --copy-up=/r>
             tq568 /proc/self/exe --net=slirp4netns --mtu=65520 --slirp4netns-sandbox=auto --slirp4netns-seccomp=auto --disable-host-loopback --port-driver=builtin --copy-up=/etc --copy-up>
             tq587 slirp4netns --mtu 65520 -r 3 --disable-host-loopback --enable-sandbox --enable-seccomp 568 tap0
             tq595 dockerd
             mq758 containerd --config /run/user/1000/docker/containerd/containerd.toml --log-level info

 4月 29 01:49:32 raspberrypi dockerd-rootless.sh[595]: time="2022-04-29T01:49:32.884200679+09:00" level=warning msg="Unable to find io controller"
 4月 29 01:49:32 raspberrypi dockerd-rootless.sh[595]: time="2022-04-29T01:49:32.884252882+09:00" level=warning msg="Unable to find cpuset controller"
 4月 29 01:49:32 raspberrypi dockerd-rootless.sh[595]: time="2022-04-29T01:49:32.888897401+09:00" level=info msg="Loading containers: start."
 4月 29 01:49:32 raspberrypi dockerd-rootless.sh[595]: time="2022-04-29T01:49:32.906821882+09:00" level=warning msg="Running modprobe bridge br_netfilter failed with message: modprobe: ERR>
 4月 29 01:49:33 raspberrypi dockerd-rootless.sh[595]: time="2022-04-29T01:49:33.861375549+09:00" level=info msg="Default bridge (docker0) is assigned with an IP address 172.17.0.0/16. Dae>
 4月 29 01:49:34 raspberrypi dockerd-rootless.sh[595]: time="2022-04-29T01:49:34.137345715+09:00" level=info msg="Loading containers: done."
 4月 29 01:49:34 raspberrypi dockerd-rootless.sh[595]: time="2022-04-29T01:49:34.526908011+09:00" level=warning msg="Not using native diff for overlay2, this may cause degraded performance>
 4月 29 01:49:34 raspberrypi dockerd-rootless.sh[595]: time="2022-04-29T01:49:34.529413307+09:00" level=info msg="Docker daemon" commit=87a90dc graphdriver(s)=overlay2 version=20.10.14
 4月 29 01:49:34 raspberrypi dockerd-rootless.sh[595]: time="2022-04-29T01:49:34.531295419+09:00" level=info msg="Daemon has completed initialization"
 4月 29 01:49:34 raspberrypi dockerd-rootless.sh[595]: time="2022-04-29T01:49:34.662640493+09:00" level=info msg="API listen on /run/user/1000/docker.sock"

これで、Dockerの導入は完了です。

動作確認

Dockerの導入が完了したので、動作確認をします。

以下のコマンドを実行してください。

# nginxのコンテナを作成(しばらくかかります)
docker run --rm -d -p 8080:80 nginx
# nginxのコンテナにアクセス
curl localhost:8080

curlコマンドを実行すると、以下のような結果が返ってくると思います。

完全に一致していなくとも、「Welcom to nginx!」が表示されていれば意図通りの動作となります

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

使用したコンテナとイメージは不要なので削除しておきます。

# コンテナの削除
docker rm -f $(docker ps -aq)
# コンテナイメージの削除
docker rmi nginx

docker-composeのインストール

今後、コンテナを一元管理していきたいため、docker-composeというものをインストールします。

これは、pipコマンドでインストールできます。

sudo pip3 install docker-compose

インストール完了後、以下のコマンドを実行し、パスが通っていることを確認します。

which docker-compose
/usr/local/bin/docker-compose

お疲れ様でした。これで、Docker環境の導入は完了です。

【追記】well-knownポートに対する対応

今回、rootlessのDockerをインストールしました。

ただ、well-knownポート(1024未満のポート)を使用する場合、rootlessのDockerではエラーが発生します。

回避方法としては、以下の2つの方法があります。

  1. 代替ポートを指定する
    http(ポート:80)の場合、8080:80とし、クライアント側で8080を指定してアクセスする
  2. CAP_NET_BIND_SERVICEの設定を行う

1番目は、Dockerやdocker-composeで、以下のように代替ポートを指定すればOKです。

# Dockerの場合
docker run [中略] -p 8080:80 [省略] # 8080番を80番にバインド
# docker-composeの場合
services:
    service1:
        [中略]
        ports:
            - "8080:80" # 8080番を80番にバインド

2番目は、クライアント側で変更できない場合の対応です。

例えば、NASサーバで利用する445/tcpなどが挙げられます。

この場合、Raspberry Piで以下のコマンドを実行します。

# well-knownポートも解放できるように設定
sudo setcap CAP_NET_BIND_SERVICE=ep $HOME/bin/rootlesskit
# Dockerサービスの再起動
systemctl --user restart docker

さいごに

今回はDocker環境を導入しました。

今後は、このDockerを用いて開発を行っていきます。

サーバの勉強にはRaspberry Piが便利だと考えています。

この機会に購入してみてはいかがでしょうか。

あわせて読みたい
【紹介】Raspberry Piの活用事例

続きを見る

スポンサードリンク



-デバイス
-,