UbuntuにDockerをインストールし、tlsによるリモート接続を行う
昔作成したコンテンツのバックアップ用記事です
Dockerのインストール
UbuntuにDockerをインストールするためには以下のコマンドを実行します
面倒がないようにコピペ一発で全て行うようにしてあります
1curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg && \2echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \3 $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null && \4sudo apt update && sudo apt install -y docker-ce
Dockerの起動設定
1sudo systemctl enable docker2sudo systemctl start docker
動作確認
デフォルトではDockerへの接続にroot権限が必要です
1sudo docker ps
一般ユーザでDockerを使えるようにする
以下のコマンド実行後、ログインし直すと使えるようになります
1sudo usermod -aG docker `logname`
確認
1docker ps
tlsによる接続
Dockerにはリモート作業時、パスワード認証のような機能はありません
httpsを利用して、暗号化ついでにコマンドを勝手に実行されないように制限をかける必要があります
そのためにはオレオレ証明書を作成しサーバとクライアントに配る必要があるのですが、これをやるのに一手間二手間かかります
余りに面倒なので、コマンド一発で終わるように、途中の入力を全てスキップするスクリプトを作成しました
証明書の作成
コマンドの説明はこちらを確認してください
https://github.com/SoraKumo001/docker-tls
リモートからで接続するための証明書を作成します
1curl -s https://raw.githubusercontent.com/SoraKumo001/docker-tls/master/docker-tls.sh | sudo bash
接続の際にホスト名を正確に設定したい場合は以下のようにドメイン名やIPを指定します
1curl -s https://raw.githubusercontent.com/SoraKumo001/docker-tls/master/docker-tls.sh | sudo bash -s DNS:host.example.com,IP:10.1.1.1
生成されるファイル
プライベートキー
/etc/docker/certs/private-key.pemDockerデーモン用ファイル
/etc/docker/certs/ca.pem
/etc/docker/certs/server-key.pem
/etc/docker/certs/server-cert.pemクライアント用ファイル
~/.docker/ca.pem
~/.docker/cert.pem
~/.docker/key.pem
各環境でリモート接続する場合は、クライアントファイルをユーザディレクトリの.dockerフォルダにコピーします
また、既存のプライベートキーを他のサーバにコピーした状態で証明書を作成すると、クライアント用ファイルが使い回せるようになります
サービスの設定変更
ファイルの書き換え
/lib/systemd/system/docker.service のExecStartを以下のように書き換えます
1ExecStart=/usr/bin/dockerd --tlsverify --tlscacert=/etc/docker/certs/ca.pem --tlscert=/etc/docker/certs/server-cert.pem --tlskey=/etc/docker/certs/server-key.pem -H tcp://0.0.0.0 -H fd:// --containerd=/run/containerd/containerd.sock
手動で編集するのが面倒な場合は、以下のコマンドを貼り付ければ書き換えが完了します
1sudo sed -i "s/^ExecStart=.*/ExecStart=\/usr\/bin\/dockerd \2--tlsverify --tlscacert=\/etc\/docker\/certs\/ca.pem \3--tlscert=\/etc\/docker\/certs\/server-cert.pem \4--tlskey=\/etc\/docker\/certs\/server-key.pem \5-H tcp:\/\/0.0.0.0 -H fd:\/\/ \6--containerd=\/run\/containerd\/containerd.sock/" \7/lib/systemd/system/docker.service
サービスの更新
1sudo systemctl daemon-reload && sudo systemctl restart docker
tlsによる接続確認
ホストを指定して接続する場合はtls接続が必須となっています
--tlsを指定しないと接続できません
--tlsverifyオプションにすると、接続時にドメイン名を検証するようになります
1docker --tls -H localhost ps
リモートでのDockerイメージの転送
Dockerのコマンドには、Dockerイメージをパイプで受け渡す機能があるので、以下のようにするとDockerHubを経由しなくてもリモートでイメージを転送できます
1docker save イメージ名(複数指定可能) | docker --tls -H サーバ名 load
ローカルで作成したイメージやCI/CDでビルドしたものを転送する場合に便利です
docker-composeから接続する場合
証明書作成時に指定したホスト名と一致しないと接続できないので注意してください
1docker-compose --tlsverify -H ホスト名:2375 以下通常コマンド
Docker volumeのバックアップとリストア
何故か標準でバックアップ方法が存在しない
DockerはImageやConteinerは簡単にバックアップがとれるのに、何故かVolumeに関しては標準的なバックアップ方法が存在しません。ということでできる限り簡単な方法を考えてみました。
ネットで検索すると出てくる方法
VolumeをマウントするConteinerを作って、バックアップを作成する方法が多数ヒットします。ただ、残念なのはその出力先です。何故かバックアップファイルをConteiner内、もしくはDockerホスト上のディレクトリに作成していました。
それをやられるとリモートでコマンドを使った場合に、手元にバックアップが残りません。作成したバックアップを何らかの手段でさらに引き寄せる必要があります。非常に面倒です。
標準入出力を使おう
dockerコマンドは標準入出力でConteinerとデータをやりとりすることが出来ます。つまりバックアップファイルを標準出力に出すだけで、コマンドを実行した環境にバックアップ結果を吐き出すことが出来ます。
バックアップコマンドを作ってみる
以下のようなコマンドを実行すると、期待通りに動いてくれます。
によるリダイレクトはConteiner上ではなく、dockerコマンドを実行したローカル環境で働くからです。
バックアップコマンド
1docker run --rm -v [Dockerボリューム]:/backup busybox tar cvz -C /backup . > [バックアップファイル名.tar.gz]
リモートのDockerホストに対してボリュームのバックアップ
1docker -H [ホスト名] run --rm -v [Dockerボリューム]:/backup busybox tar cvz -C /backup . > [バックアップファイル名.tar.gz]
リモートのバックアップした場合も、もちろんローカル環境にバックアップをとることが出来ます。
リストアコマンドを作ってみる
リストアコマンド
dockerコマンドで-iを使い、標準入力を使えるようにします。
1docker run --rm -i -v [Dockerボリューム]:/backup busybox tar xvz -C /backup < [バックアップファイル名.tar.gz]
リモートのDockerホストに対してボリュームのリストア
1docker -H [ホスト名] run --rm -i -v [Dockerボリューム]:/backup busybox tar xvz -C /backup < [バックアップファイル名.tar.gz]
高速化したい
バックアップやリストアは出来るようになりましたが、もっと高速に処理したくなります。tarでzオプションを使うとgzipが使われますが、これをpigzのような並列処理対応のコマンドで置き換えれば、ホスト側のCPUのコア数に応じて高速化が見込めます。しかしざっと探したところ、pigzが入っている軽量Imageが見つかりません。もしかしたらどこかにあるかもしれませんが、探すより作った方が早いので作ることにしました。
pigz付きalpineのImageを作成します。
コマンドを書かなくても良いように、CMDも設定しておきます。
バックアップ用Imageを作成する
バックアップ
1FROM alpine2RUN apk --no-cache add pigz3CMD sh -c "tar cv -C /backup . | pigz"
リストア
1FROM alpine2RUN apk --no-cache add pigz3CMD sh -c "pigz -d | tar xv -C /backup"
Docker Hubに登録
個人アカウント名で置くのが微妙だったので、dktoolsという組織名を作りました。
・置き場所
バックアップ
https://hub.docker.com/r/dktools/backup
リストア
https://hub.docker.com/r/dktools/restore
・使い方
バックアップ
1docker run --rm -v [DOCKER-VOLUME]:/backup dktools/backup > backup.tar.gz
リストア
1docker run --rm -i -v [DOCKER-VOLUME]:/backup dktools/restore < backup.tar.gz
今のところパラメータ指定などはありませんが、気が向いたらそのうち機能を追加します。
まとめ
私の場合Dockerはtls接続でリモート管理しているので、バックアップをローカルに呼び寄せないと面倒なので、今回のようなものを作成しました。ちなみにsshのポートフォワードをしている場合も、リモートバックアップは可能です。ただtlsで直接接続している場合とポートフォワードでは、ポートフォワードの転送速度が数倍遅いので、出来ることならtls設定を入れた方が効率は上がります。
。