これは フェンリル デザインとテクノロジー Advent Calendar 2022 4日目の記事です。
Dockerを使う方の中には build
や up
コマンドくらいしか使ったことない方も大勢いるのではないでしょうか。Dockerのコマンド一覧のドキュメントを見てみると、見たことすら無いものもたくさんあると思います。
今回はたくさんある機能の中から、リモートのDockerを便利に使うためのコマンドを2つ紹介したいと思います。
作業環境
以降の作業は以下の環境で実行したものです。
- PC : MacBook Pro 13-inch 2020
- OS : macOS Ventura 13.0.1
- Docker Engine :
20.10.21
docker save / docker load
ビルドしたDockerイメージをリモートのサーバーに持っていきたいけど、レジストリを用意するほどでもない…。そんなときにはこのコマンドを使ってみましょう。
コマンドの使い方は以下のとおりです。
$ docker save [OPTIONS] IMAGE [IMAGE...]
Name, shorthand | Default | Description |
---|---|---|
--output , -o | Write to a file, instead of STDOUT |
$ docker load [OPTIONS]
Name, shorthand | Default | Description |
---|---|---|
--input , -i | Read from tar archive file, instead of STDIN | |
--quiet , -q | Suppress the load output |
引用元 : docker save / docker load
事前に Hello World と出力するだけのDockerイメージを作成しておきます。
FROM alpine:latest
CMD ["echo","Hello World"]
ビルドと実行をします。
$ docker build -q -t helloworld .
sha256:b8e5160def5593aab3002009595fcdd031d249bbc240f26260090f88bfe36c2f
$ docker image ls helloworld
REPOSITORY TAG IMAGE ID CREATED SIZE
helloworld latest b8e5160def55 13 days ago 7.05MB
$ docker run --rm helloworld
Hello World
Hello World と出力されています。
ではこのイメージを docker save
コマンドでアーカイブファイルとして出力してみましょう。
$ docker save helloworld > helloworld.tar
$ ls -lah helloworld.tar
-rw-r--r-- 1 yoneda staff 7.0M 12 4 00:00 helloworld.tar
tar
ファイルとして保存されました!
本当に保存されたか確認するために、先程ビルドしたDockerイメージを削除してみましょう。
$ docker rmi helloworld
Untagged: helloworld:latest
Deleted: sha256:b8e5160def5593aab3002009595fcdd031d249bbc240f26260090f88bfe36c2f
イメージの削除ができたので、出力されたアーカイブファイルから docker load
コマンドでイメージを読み込ませてみましょう。
$ docker load -q < helloworld.tar
Loaded image: helloworld:latest
$ docker image ls helloworld
REPOSITORY TAG IMAGE ID CREATED SIZE
helloworld latest b8e5160def55 13 days ago 7.05MB
一覧に helloworld
のイメージが復活していますね。では実行してみましょう。
$ docker run --rm helloworld
Hello World
Hello World が出力されました!!
このように docker save
/ docker load
コマンドを使うことで、レジストリを用意することなくDockerイメージをファイルとして自由に持ち運ぶことができます。scp
コマンドを利用すれば別のサーバーに持っていくこともできますね。
注意点としては、Docker Hub等のレジストリを使う場合にはイメージを複数に分割して並列でアップロード・ダウンロードが実行されるのですが、docker save
/ docker load
の場合は単一のファイルとして転送することになるため、大きなイメージになればなるほど転送時間が長くなってしまいます。gzipで圧縮をするなどの工夫をしましょう。
docker context
リモートのサーバー上で動いているDockerを操作するために、まずはSSHで接続してから、ディレクトリを移動して、dockerコマンドを打ち込んで…。こんな操作を頻繁にしている人も多いのではないでしょうか。そんなときにはこのコマンドを使ってDockerをリモートで操作してみましょう。
まずはリモートで動作するDockerを準備します。ここでは以下のようなAWS EC2を利用します。
- Instance type : t3.medium
- AMI ID :
ami-072bfb8ae2c884cc4
(Amazon Linux 2 Kernel 5.10) - Public IP address :
54.248.12.145
注意点としては、外部からTCP 2375番ポートを経由してDockerを操作することになるため、何らかの手段で経路を確保する必要がある点です。EC2の場合はSystems ManagerのSession Managerを使って2375番ポートをローカルにポートフォワードさせる事を推奨します。
今回は作業を簡易的にするため、EC2インスタンスをパブリックネットワークに作成することでパブリックIPを割り当て、セキュリティグループで該当ポート経由の通信を許可するように設定します。
EC2インスタンスの起動が完了したらDockerのインストールと起動をします。
$ sudo amazon-linux-extras install docker
Installing docker
...
(省略)
...
$ sudo systemctl start docker
● docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; vendor preset: disabled)
Active: inactive (dead)
Docs: https://docs.docker.com
$ sudo docker -v
Docker version 20.10.17, build 100c701
次にDaemon socket optionを使い、TCP 2375番で待ち受ける設定を追加します。/var/lib/systemd/system/docker.service
の ExecStart
で始まる行を確認します。
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock $OPTIONS $DOCKER_STORAGE_OPTIONS $DOCKER_ADD_RUNTIMES
ここに -H tcp://0.0.0.0:2375
を追加しましょう。
公式ドキュメント : Daemon CLI (dockerd) / Daemon socket option
ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2375 --containerd=/run/containerd/containerd.sock $OPTIONS $DOCKER_STORAGE_OPTIONS $DOCKER_ADD_RUNTIMES
設定を変更したら、Dockerを再起動します。
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
これでリモート側の準備は完了です。ここからはローカルPC側の設定をしていきます。 docker context create
コマンドでリモートのDockerを登録しましょう。
コマンドの使い方は以下のとおりです。
$ docker context create [OPTIONS] CONTEXT
Name, shorthand | Default | Description |
---|---|---|
--default-stack-orchestrator | (deprecated)Default orchestrator for stack operations to use with this context (swarm|kubernetes|all) | |
--description | Description of the context | |
--docker | set the docker endpoint | |
--from | create context from a named context | |
--kubernetes | (deprecated)(Kubernetes) set the kubernetes endpoint |
引用元 : docker context create
--docker
オプションを利用して、先程設定したリモートで動いているDockerのエンドポイントを指定します。
$ docker context create --docker host=tcp://54.248.12.145:2375 remote
remote
Successfully created context "remote"
remote
という名前で作成が完了しました。それでは --context
オプションを付けてローカルからリモートのDockerを操作し、適当なイメージをPullしてみましょう。
$ docker --context remote pull docker/whalesay
Using default tag: latest
latest: Pulling from docker/whalesay
Image docker.io/docker/whalesay:latest uses outdated schema1 manifest format. Please upgrade to a schema2 image for better future compatibility. More information at https://docs.docker.com/registry/spec/deprecated-schema-v1/
e190868d63f8: Pull complete
909cd34c6fd7: Pull complete
0b9bfabab7c1: Pull complete
a3ed95caeb02: Pull complete
00bf65475aba: Pull complete
c57b6bcc83e3: Pull complete
8978f6879e2f: Pull complete
8eed3712d2cf: Pull complete
Digest: sha256:178598e51a26abbc958b8a2e48825c90bc22e641de3d31e18aaf55f3258ba93b
Status: Downloaded newer image for docker/whalesay:latest
docker.io/docker/whalesay:latest
Pullが完了しました。リモート側のターミナルに接続してイメージの確認をしてみましょう。
$ sudo docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
docker/whalesay latest 6b362a9f73eb 7 years ago 247MB
先程ローカルから操作してPullしたイメージが保存されていることが確認できました。
応用してみる
今回紹介した docker save
/ docker load
と docker context
ですが、組み合わせて使うことができます。前半に docker save
で出力した helloworld.tar
を、--context
オプションを付けてリモートのDockerに docker load
で読み込ませてみましょう。
$ docker --context remote load < helloworld.tar
ded7a220bb05: Loading layer [==================================================>] 7.338MB/7.338MB
Loaded image: helloworld:latest
$ docker --context remote image ls helloworld
REPOSITORY TAG IMAGE ID CREATED SIZE
helloworld latest b8e5160def55 13 days ago 7.05MB
$ docker --context remote run --rm helloworld
Hello World
ビルドしたイメージをリモートのDockerに転送して実行することができました。簡易的なデプロイが実現できましたね。
まとめ
たくさんあるDockerの機能の中から、今回は docker save / docker load
と docker context
を紹介しました。あまり使っている例を見かけないコマンドたちではありますが、いざ使ってみると「こんなことにも使えるのでは…?」となったのではないでしょうか。
これ以外にもDockerには様々なコマンドが用意されているので、どんどん試してDockerマスターを目指しましょう!!!