tl;dr
個人的に利用している MacBook Air (11-inch, Mid 2012) は, まだ macOS Mojave のアップグレード対象になっていたりして, Apple から見放されていないようなので, しばらくは使い続けようかなと考えています. また, 購入時に奮発してメモリ 8GB にしたお陰で, 基本的な操作 (インターネットを見る, vim で何かを書く) であれば十分現役だと思っています. ということで, 今回, 利用する端末の情報は下記の通りです.
以下, OS の情報.
$ sw_vers ProductName: Mac OS X ProductVersion: 10.14.2 BuildVersion: 18C54
以下, ハードウェアの情報.
しかし, Docker for Mac を使っていて, Docker for Mac だけでメモリの使用量が 2GB だったりするのを見ると, 「おおっ」という気分になって Docker 環境を VPS あたりに逃してあげればメモリ使用量を抑えることが出来るよなーという思いから docker-machine と DigitalOcean を使って VPS 上に Docker 環境を揃えてみました.
頼りになるのは, 近くの VM より遠くの VPS
DigitalOcean
すでに DigitalOcean のアカウントは取得済み, アクセストークンも払い出し済みという前提で進めます. また, VPS を起動した後, 仮想マシン (以降は Droplet と呼びます) に対して Firewall の設定等を行いたいので, DigitalOcean が提供する各種リソースをコマンドラインで操作出来る doctl というツールを事前にインストールしておきましょう.
brew install doctl
今回, doctl については, 以下のバージョンを利用します.
$ doctl version doctl version 1.12.2-release
尚, DigitalOcean の VPS にはいくつかのプラン (インスタンスタイプみたいなもの) がありますが, 今回は, 一番安価な メモリ 1GB, 1vCPU, 25GB SSD のタイプを利用します. このタイプですと, 1 時間あたり $0.007 ドル, 1 ヶ月に換算すると $5 となりますので, 一年稼働し続けても 7000 円程度と, これから MacBook Pro 13 インチあたりを新調するよりはお安く済みそうな気がします.
docker-machine
以下のバージョンの docker-machine を利用します.
$ docker-machine version docker-machine version 0.16.0, build 702c267f
Docker 用の Droplet を起動
例のごとく, direnv を手元に用意しておくと良いでしょう. 以下のように .envrc の中に DigitalOcean のトークンを書いておきます.
export DIGITALOCEAN_ACCESS_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
以下のように docker-machine を実行します.
docker-machine create \ --driver digitalocean \ --digitalocean-access-token=${DIGITALOCEAN_ACCESS_TOKEN} \ my-docker-host
以下, 実行例です.
$ docker-machine create \ > --driver digitalocean \ > --digitalocean-access-token=${DIGITALOCEAN_ACCESS_TOKEN} \ > my-docker-host Running pre-create checks... Creating machine... (my-docker-host) Creating SSH key... (my-docker-host) Creating Digital Ocean droplet... (my-docker-host) Waiting for IP address to be assigned to the Droplet... Waiting for machine to be running, this may take a few minutes... Detecting operating system of created instance... Waiting for SSH to be available... Detecting the provisioner... Provisioning with ubuntu(systemd)... Installing Docker... Copying certs to the local machine directory... Copying certs to the remote machine... Setting Docker configuration on the remote daemon... Checking connection to Docker... Docker is up and running! To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: docker-machine env my-docker-host
docker-machine env my-docker-host
を実行して, IP アドレス等を確認しましょう. 以下のように出力されます.
$ docker-machine env my-docker-host export DOCKER_TLS_VERIFY="1" export DOCKER_HOST="tcp://xxx.xx.xx.xx:2376" export DOCKER_CERT_PATH="/Users/user/.docker/machine/machines/my-docker-host" export DOCKER_MACHINE_NAME="my-docker-host" # Run this command to configure your shell: # eval $(docker-machine env my-docker-host)
また, eval $(docker-machine env my-docker-host)
を実行して環境変数に指定してしまいましょう.
Firewall を設定する
Droplet を作成するとデフォルトだと Firewall の設定は行われていません. この状態だと, どこからでも SSH アクセスが出来たり, Docker API を叩くことが可能な状態になっています. ただし, SSH でログインするには SSH キーが必要だったり, Docker にリモートアクセスする為のキーが必要だったりするので, 誰でもどこからでもアクセス出来るという状態ではありませんが...気持ち悪いので, 固定 IP からのみアクセスを許可するように Firewall を設定します.
事前に DigitalOcean の Web コンソール上で Firewall の設定をしておきましょう. 今回は MyNetwork という Firewall のエントリを事前に作成しておきましたので, 以下のように Firewall の ID と Droplet の ID を取得して Droplet に Firewall をアタッチします.
FIREWALL_ID=$(doctl compute firewall list --output=json | jq -r '.[]|select(.name | test("MyNetwork")) | .id') DROPLET_ID=$(doctl compute droplet list --output=json | jq -r '.[]|select(.name | test("my-docker-host")) | .id') doctl compute firewall add-droplets ${FIREWALL_ID} --droplet-ids ${DROPLET_ID}
一通り設定が終わったら
docker-machine ls
してみましょう.
$ docker-machine ls NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS my-docker-host * digitalocean Running tcp://xxx.xx.xx.xx:2376 v18.09.1
docker-machine の設定を確認してみましょう.
$ docker-machine config my-docker-host --tlsverify --tlscacert="/Users/user/.docker/machine/machines/my-docker-host/ca.pem" --tlscert="/Users/user/.docker/machine/machines/my-docker-host/cert.pem" --tlskey="/Users/user/.docker/machine/machines/my-docker-host/key.pem" -H=tcp://xxx.xx.xx.xx:2376
これで Docker を操作してみましょう
docker ps
してみましょう.
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Nginx のコンテナを起動してみましょう.
$ docker run -p 80:80 -d nginx Unable to find image 'nginx:latest' locally latest: Pulling from library/nginx 177e7ef0df69: Pull complete ea57c53235df: Pull complete bbdb1fbd4a86: Pull complete Digest: sha256:b543f6d0983fbc25b9874e22f4fe257a567111da96fd1d8f1b44315f1236398c Status: Downloaded newer image for nginx:latest 6b55bf40f43b261e97c2fcb02c729e9c26867d3aa07787d5cd55d56f42fd799a
ローカルホストではないので, コンテナにアクセスする為に docker-machine ip my-docker-host
を実行して Droplet の IP アドレスを確認しつつ , 以下のように実行します.
$ curl $(docker-machine ip my-docker-host) -I HTTP/1.1 200 OK Server: nginx/1.15.8 Date: Sat, 19 Jan 2019 08:51:12 GMT Content-Type: text/html Content-Length: 612 Last-Modified: Tue, 25 Dec 2018 09:56:47 GMT Connection: keep-alive ETag: "5c21fedf-264" Accept-Ranges: bytes
いい感じです.
後始末
以下のように実行して Docker ホストを削除します. Droplet は一瞬で削除されるので驚きです.
docker-machine rm my-docker-host
以下, 実行例です.
$ docker-machine rm my-docker-host About to remove my-docker-host WARNING: This action will delete both local reference and remote instance. Are you sure? (y/n): y Successfully removed my-docker-host $ doctl compute droplet list --output=json null