LoginSignup
92
106

More than 3 years have passed since last update.

Docker for Mac が遅いので代わりに VirtualBox 上で Docker を使う

Last updated at Posted at 2020-05-02

Node.js の開発では Docker for Mac が便利ですが、仕組み的にディスクアクセスが遅くなるので、処理性能が半分とまではいかないものの、3割くらい遅いです。そこで Docker for Mac のお手軽環境を諦めて、代わりに VirtualBox 上で Docker を使うと、ほとんど性能劣化なく動くようです。

VirtualBox 上で動かす VM は何でも良いのですが、プロダクション環境は AWS が多いので、今回は VM にも Amazon Linux 2 を使うことにします。各ファイルも VirtualBox 上の VM 側に置いて、Mac から NFS でアクセスします。

(1) VirtualBox をインストールする。

https://www.virtualbox.org/wiki/Downloads の「OS X hosts」から、VirtualBox をダウンロード・インストールする。120MB くらい。
virtualbox.jpg

(2) VirtualBox > ファイル > ホストネットワークマネージャー > 作成

  • 作成ボタンを押すと、ネットワーク vboxnet0 ができる。
  • IPv4 アドレスをメモしておく。ここでは「192.168.56.1/24」になっている。 vboxnet0.jpg

(3) Amazon Linux 2 の VM イメージをダウンロードする。

https://cdn.amazonlinux.com/os-images/latest/virtualbox/ から
最新の VM イメージ amzn2-virtualbox-2.0.20200304.0-x86_64.xfs.gpt.vdi をダウンロードする。1.5GB。
(Amazon Linux 2 LTS 2.0.20200304.0 x86_64 VirtualBox image)

(4) cloud-init 用の ISO イメージ (cidata) を作成する

mkdir -p ~/Desktop/amzn2
cd ~/Desktop/amzn2
mkdir seedconfig

cat <<__EOT__>seedconfig/meta-data
local-hostname: amzn2
__EOT__

cat <<__EOT__>seedconfig/user-data
#cloud-config
# ↑1行目の「#cloud-config」を抜かないこと。

# デフォルトで ec2-user ユーザが作成される。
users:
  - default

# ec2-user ユーザのパスワードを指定する。: の後にスペースを入れると、スペース入りのパスワードになるので注意。
chpasswd:
  list:
    - "ec2-user:amazon"

# あとで eth1 を作るために、vboxnet0 のネットワーク内の IP アドレスを指定する。
write_files:
  - path: /etc/sysconfig/network-scripts/ifcfg-eth1
    content: |
      BOOTPROTO=static
      DEVICE=eth1
      IPADDR=192.168.56.78
      ONBOOT=yes
      TYPE=Ethernet
      PREFIX=24
      PEERDNS=no
      IPV6INIT=no
      DEFROUTE=no
      EC2SYNC=no
      USERCTL=no
      PERSISTENT_DHCLIENT=no
__EOT__

mkdir -p ~/VirtualBox\ VMs

# ISO イメージを作成する
hdiutil makehybrid -o ~/VirtualBox\ VMs/seed.iso -hfs -joliet -iso -default-volume-name cidata seedconfig/

# ダウンロードした VM イメージも、コピーしてから使う
cp -p ~/Downloads/amzn2-virtualbox-2.0.20200304.0-x86_64.xfs.gpt.vdi ~/VirtualBox\ VMs/amzn2.xfs.dvi

(5) VirtualBox > 仮想マシン > 新規

  • 名前:amzn2
  • マシンフォルダー:/Users/xxxx/VirtualBox VMs(デフォルト)
  • タイプ:Linux
  • バージョン:Linux 2.6 / 3.x / 4.x (64-bit)
  • メモリーサイズ:2048MB
  • ハードディスク:すでにある仮想ハードディスクファイルを使用する → amzn2.xfs.dvi を選択 5-1-machine.jpg

(6) amzn2 > 設定 > ストレージ

  • コントローラー:IDE の右側の [+] ボタンから、seed.iso を追加する。
  • 画面下部の「新しいストレージコントローラを追加します」「新規のストレージ割り当てを追加します」ではなくて、「光学ドライブの追加」を選ぶ。 6-storage.jpg

(7) amzn2 > 設定 > ネットワーク > アダプター1

  • ネットワークアダプターを有効化:ON(まま)
  • 割り当て:NAT
  • 備考:アダプター1= eth0 は、VM からの上り回線用。Mac 側の上流回線が何でもOK。LAN 内から VM へのアクセスを防ぐ。 7-eth0.jpg

(8) amzn2 > 設定 > ネットワーク > アダプター2

  • ネットワークアダプターを有効化:ON
  • 割り当て:ホストオンリーアダプター
  • 名前:vboxnet0
  • 備考:アダプター2=eth1 は、Mac から VM への接続用。eth0 をリセットしても、eth1 は通じる。 8-eth1.jpg

(9) amzn2 > 起動

  • VM を起動する。
  • 初回は ssh が効かないので、VirtualBox の画面から ec2-user ユーザでログインする。
  • cloud-init の設定をすれは、初回から SSH 接続できるだろうけど、デフォルトではできないので、妥協。 login-screen.jpg
# 以下は VM 内で実行する
sudo su -

# ホストオンリーアダプターを有効化する
ifup eth1

# 自分のアクセス用のユーザ foobar を作成する。
# 自分の uid と docker の gid は固定しておくと、あとで面倒がない。
# ここでは 1234 としているが、1001 を指定した方が便利かも?
adduser -M -u 1234 foobar
groupadd -g 987 docker
usermod -aG docker foobar

# ssh 公開鍵 authorized_keys を設定せずに、パスワードで SSH 接続する場合
passwd foobar
sed -i 's/^PasswordAuthentication no/PasswordAuthentication yes/' /etc/ssh/sshd_config
systemctl reload sshd

(10) Mac から SSH 接続でログインする

# Mac 側の Terminal.app で実行する
echo "192.168.56.78 amzn2" | sudo tee -a /etc/hosts
ssh foobar@amzn2

# 以下は VM 内で実行する
sudo su -

#(オプション)ダウンロードした .rpm パッケージを残したい場合
sed -i 's/^keepcache=0/keepcache=1/' /etc/yum.conf

#(オプション)yum や apk のキャッシュ用に Squid を入れる場合
yum install -y squid
systemctl enable squid 
systemctl start squid 
tail -f /var/log/squid/access.log /var/log/squid/cache.log 
echo 'proxy=http://127.0.0.1:3128' >> /etc/yum.conf

#(オプション)他にも必要なパッケージがあればインストールする
yum update -y
yum install -y git

(11) Docker を使う

ssh foobar@amzn2
# 以下は VM 内で実行する

# Docker をインストールする
sudo yum install -y docker
sudo systemctl enable docker 
sudo systemctl start docker

# foobar ユーザ権限でも Docker を使えるのを確認する
docker run hello-world

(12) NFS サーバを設定する

ssh foobar@amzn2

# 以下は VM 内で実行する
sudo su -

# NFS をインストールする
yum install -y nfs-utils
systemctl start nfs-server.service
systemctl enable nfs-server.service

# ホストオンリーアダプター(自分の Mac)からのみ NFS 接続を許可する
echo "/home/foobar 192.168.56.0/24(rw,sync,no_subtree_check,insecure,all_squash,anonuid=1234,anongid=1234)" > /etc/exports
exportfs -ar # 更新
exportfs -v # 確認

(12) Mac から NFS をマウントする

# Mac 側の Terminal.app で実行する
sudo mkdir /Volumes/foobar
sudo mount -t nfs amzn2:/home/foobar /Volumes/foobar

# Mac から NFS 経由でアクセスできるようになった
ls -l /Volumes/foobar
df -m /Volumes/foobar
open /Volumes/foobar

# マウント解除する場合(Finder.app からもアンマウントできる)
sudo umount /Volumes/foobar

あるいは、NFS でなくて Samba でも、VM 内のファイルを Mac から操作できますが、NFS の方が良さそう。
VM を動かすホストを別マシンに分けても(有線 LAN なら)NFS 経由で問題ない速度でアクセスできます。

(備考)Samba と NFS の比較:

Samba
⭕ Finder からマウント操作できるので分かりやすい
⭕ 設定でアクセスするユーザアカウントを指定可能。
❌ パーミションの互換性や、シンボリックリンクで面倒な事態が発生

NFS
⭕ 1ユーザの環境なら、パーミションも問題なし。
⭕ UNIX 同士なので、シンボリックリンクも問題なし。
❌ マウントするときに mount コマンドを叩く必要がある(切断は Finder から操作できる)


PS.
Docker for Mac ができる前の時代に戻った感覚ですが、ちょっとこれでしばらく運用してみようかと。
Node.js については Docker for Mac もまだ現実的な速度なんだけど、PHP (WordPress) はファイルアクセスが多いためか、数倍は遅くて、使い物になりませんでした。
『Alpine のメモリが遅い』という話もみかけましたが、Node.js については、試した限りでは、メモリは問題なくて、ディスクアクセスの影響が大きいように感じています。
Windows なら WSL 2 でそろそろ直接 Docker が動くようなので、羨ましいですね。

92
106
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
92
106