LoginSignup
6
11

More than 3 years have passed since last update.

MAC環境でVirtualBox+Vagrant+DockerでReact開発環境を作る╰(°ㅂ°)╯

Last updated at Posted at 2020-05-15

#stayhomeの時間を活用して、「仮想環境」とか「コンテナ開発」とかに慣れ親しもうという魂胆です。作業を進める上でよくわからなかった点など、周辺情報を個人的な備忘録として残します。

ゴール

作ったり壊せたり自由にできる開発環境を立ち上げられるようになること。React.jsの勉強を始める予定なので、React.jsの雛形アプリをブラウザで表示させるところまでをゴールとする。

作業の流れ

ステップが多く、私のような初学者は、わからない部分を調べている間に迷子になることもしばしば。一つ一つの動作確認をしながら作業を進めていきます。

【前半戦:ホストOS側での作業】

  • 事前準備
    • vagrantプラグインの導入確認
  • VMの設定
    • vagrant初期化
    • Vagrantfileの編集
  • dockerとdocker-composeの導入
    • Dockerfileの作成
    • docker-compose.ymlの作成
  • ホストOSとゲストOS間のファイル同期の設定
    • mutagen.yml作成

【後半戦:ゲストOS側での作業】

  • VM起動
    • vagrantでVM起動
    • VMにssh接続
  • VMの動作確認
    • ホストOSとのフォルダ共有を確認
    • dockerとdocker-compose動作
  • React.jsの導入
    • Dockerコンテナの起動
    • 起動中のコンテナに入る
    • create-react-appのインストールとアプリのひな形作成
    • アプリの実行

教材

基本となる教科書はこちらの二冊(記事)です。
- Vagrantを使う「Mac最速のDocker環境」を初心者向けに解説【遅いMac for Dockerを卒業】
- DXを大幅に低下させるDocker for Macを捨ててMac最速のDocker環境を手に入れる

その他、以下のQiita記事を参考にさせていただきました。
- Docker環境内でcreate-react-app
- Windows環境においてVirtualBox+Vagrant+DockerでReact開発環境を作る*Windows向けに書かれた記事ですが、仮想環境起動のパート以降の後半部分を中心に参考にしました。

作業ディレクトリ

作業を行うディレクトリは、ホームフォルダ下に置いてある開発(develop)ファイルにVM(仮想マシン)フォルダを作成。その配下にsample-pjなる場所を作りました。
/Users/home/develop/vm/sample-pj

実行環境・ソフトウェア・パッケージ・プラグイン

  • macOS Mojave version 10.14.6
  • VirtualBox Version 6.1.6
  • Vagrant 2.2.9
  • VirtualBox Image ubuntu/xenial64
  • Vagrant Plugin
    • vagrant-disksize
    • vagrant-hostsupdater
    • vagrant-mutagen
    • vagrant-docker-compose
  • Docker version 19.03.8
  • docker-compose version 1.24.0

前提

Vagrantを使う「Mac最速のDocker環境」を初心者向けに解説【遅いMac for Dockerを卒業】に習って、以下のステップまで進めた状態からスタートします。

  • VirtualBoxをインストール
  • Vagrantをインストール
  • Vagrant Boxをダウンロード
  • プラグインの導入
~/develop/vm/sample-pj
$ vagrant box list
ubuntu/xenial64 (virtualbox, 20200505.0.0)

$ vagrant plugin list
vagrant-disksize (0.1.3, global)
vagrant-docker-compose (1.5.1, global)
vagrant-hostsupdater (1.1.1.160, global)
vagrant-mutagen (0.1.2, global)

この↑状態が確認できたところから開始です(`ω´)

【前半戦:ホストOS側での作業】

VMの設定

vagrant初期化

~/develop/vm/sample-pj
$ vagrant init ubuntu/xenial64

# 上記コマンドを実行して、下のような結果が出てくれば完了。
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.
何が起きたかチェーーーーーック( ·∀·)ノ
~/develop/vm/sample-pj
$ ls

# sample-pj(プロジェクトディレクトリ)内の構造を見てみると、
# Vagrantfileができていることが確認できます。
Vagrantfile

Vagrantfileの編集

Vagrantfileは、仮想機械を構築するための構成情報を記述するための設定ファイルです。

( ˘ω˘ )? 「Vagrantfileにどんなことが書かれているのか?」という疑問については、Vagrantにおける仮想マシンの設定に素敵な感じにまとまっているので、詳しくはそちらを参照ください。

~/develop/vm/sample-pj
# vimエディタでVagrantfileを開きます。
$ vim Vagrantfile

# -*- mode: ruby -*-
# vi: set ft=ruby :
# All Vagrant configuration is done below. The "2" in Vagrant.configure
(略)

Vimエディタの使い方については、Vim初心者に捧ぐ実践的入門などのQiita記事を参考にしてください。初見では、とっつきにくい見た目をしていますが、何度か触っているうちに慣れてきました。

早速、教科書=(Vagrantを使う「Mac最速のDocker環境」を初心者向けに解説【遅いMac for Dockerを卒業】)のVagrantのセットアップを参照して、Vagrantfileを編集します。

~/develop/vm/sample-pj(ホストOS内プロジェクトディレクトリ)
# /sample-pj/Vagrantfile
Vagrant.configure('2') do |config|

  # VMを立ち上げる際のboxの指定
  config.vm.box = 'ubuntu/xenial64'

  # VMに設定するホスト名
  # 後述のmutagen.yml内の記述と揃える必要があるので覚えて置くこと。
  config.vm.hostname = 'sample-app'

  config.vm.network :private_network, ip: '192.168.50.10'
  # ポートへフォワードの設定
  config.vm.network "forwarded_port", guest: 3000, host: 3000

  config.vm.provider :virtualbox do |vb|
    vb.gui = false
    vb.cpus = 4
    vb.memory = 4096
    vb.customize ['modifyvm', :id, '--natdnsproxy1', 'off']
    vb.customize ['modifyvm', :id, '--natdnshostresolver1', 'off']
  end

  config.disksize.size = '30GB'
  config.mutagen.orchestrate = true

 # config.vm.synced_folderは、ホストOSとゲストOS間で共有するフォルダを指定します。
  config.vm.synced_folder './', '/home/vagrant/app', type: "rsync",
    rsync_auto: true,
    rsync__exclude: ['.git/', 'node_modules/', 'log/', 'tmp/']

  # config.vm.provisionは、初回(VM作成時)に実行されます。
  # ここではDockerとdocker-composeの導入について書かれています。
  config.vm.provision :docker, run: 'always'

  # docker-compose の設定
  config.vm.provision :docker_compose,
    yml: "/vagrant/docker-compose.yml",
    compose_version: "1.24.0",
    run: "always"
end

ここで詰まった!!ERR_CONNECTION_REFUSEDエラー(´ε`;)

ポートへフォワードの設定とdocker-composeのインストールについては、私が追記編集した部分です。

ポートフォワードの設定については、Vagrant + VirtualBoxで仮想環境側のポートをあけるを参考にしました。この記述なし(教科書通り)で作業を進め、ブラウザでhttp://localhost:3000/ でアプリを開いてみようとすると、ERR_CONNECTION_REFUSEDという下記のエラーが出てきて困ってしまいましたが、ポートフォワードの設定を加えて解決できました。

ブラウザ(http://localhost:3000/)

This site can’t be reached
localhost refused to connect.

Try:
Checking the connection
Checking the proxy and the firewall

ERR_CONNECTION_REFUSED

ここで詰まった!!docker_composeがvagrant upでインストールされない(´ε`;)

docker-compose の設定ですが、教科書通りにconfig.vm.provision :docker_composeだけでは、vagrant up時にインストールされませんでした。バージョン情報などを追加し、無事インストールできるようになりました。原因は全くわかりません・・・。

dockerとdocker-composeの導入

Vagrantfileでは、config.vm.provisionの部分で、初回のvagrant up(VM作成時)にdockerとdocker-composeがインストールされるように設定しました。

以下では、docker-compose upによるコンテナ実行時に呼び出される、docker-compose.ymlとDockerfileの2つを作成していきます。

docker-compose.ymlの作成

~/develop/vm/sample-pj(ホストOS内プロジェクトディレクトリ)
# docker-compose.ymlを作成
vagrant@sample-app:~/app$ vi docker-compose.yml

# 下記のように書き換え
version: "3"
services:
  #コンテナ名。後ほど、この名前を指定してコマンドを叩くことになります。
  node: 
    build:
      # 参照するファイルのある場所を、docker-compose.ymlからの相対パスで指定。
    # 今回は同じ階層・同じフォルダ内にあるので、下記のような表記になる。
      context: .
    # 参照するファイル。今回はDockerfile_nodeという名前です。
      dockerfile: Dockerfile_node 
    # ストレージの指定 ホストOS:ゲストOS
    volumes:
      - ./:/usr/src/app
    ports:
      - "3000:3000"
    # docker-compose up後、即コンテナが終了することなく、待機状態とする。
    tty: true

Dockerfileの作成

~/develop/vm/sample-pj(ホストOS内プロジェクトディレクトリ)
# Dockerfileを作る。
# docker-compose.ymlで指定した通り、今回はDockerfile_nodeという名前にします。
$ vi Dockerfile_node

# Dockerfileを編集

# どのイメージを基にするか。今回はreactの開発環境なので、node.jsを使用します。
# 現時点で最新・コンパクトなバージョンを指定しました。
FROM node:14.2-alpine

# 作業ディレクトリ
WORKDIR /usr/src/app

作業ディレクトリ(WORKDIR)については、色々なサイトを見ましたが、Linux系では/usr/src/appがお作法になっているようです。「/usr/src/appとは?」という疑問に関しては、 Linux豆知識 217「/usr/src」ディレクトリを参照。

ホストOSとゲストOS間のファイル同期の設定

Vagrantfileの config.vm.synced_folderの記述で、ホストOSとゲストOS間で共有するフォルダを指定しましたが、config.vm.synced_folderによるファイル共有は、vagrant upによるVM作成時のみ実行されます。つまり、常時シンクロしてくれるわけではないそうです。

DXを大幅に低下させるDocker for Macを捨ててMac最速のDocker環境を手に入れる - ファイル同期の手段に習って、ホストOSとゲストOS間のファイル同期は、後述のmutagenというプラグインを使います。

mutagen.yml作成

DXを大幅に低下させるDocker for Macを捨ててMac最速のDocker環境を手に入れる - ファイル同期のソリューション 「Mutagen」参考に、mutagen.ymlを作成、編集していきましょう。

~/develop/vm/sample-pj(ホストOS内プロジェクトディレクトリ)
# touchコマンドでmutagen.yml新規作成
$ touch mutagen.yml 

# sample-pj(プロジェクトディレクトリ)内の構造を見てみると、mutagen.ymlが追加されているのが確認できます。
$ ls
# 実行結果↓
Vagrantfile mutagen.yml
~/develop/vm/sample-pj(ホストOS内プロジェクトディレクトリ)
# multagen.ymlファイルを開く
$ vim mutagen.yml

# multagen.yml内を編集
sync:
  app:
    # 双方向同期モード 但し、alphaが優先、ベースになる
    mode: "two-way-resolved"
    # alphaとbetaでエンドポイントを指定
    alpha: "./"
    # sample-appというhostの中の、/home/vagrant/appディレクトリ
    # sample-appは、Vagrantfile内のconfig.vm.hostname = 'sample-app'で指定した名前と揃える必要があります
    beta: "sample-app:/home/vagrant/app"
    # ignore(=無視)なので、以下に掲げる内容を無視するということかな?
    ignore:
    # vcs....バージョン管理システム(Version Control System)のことかな?それがtrueとは...? よく、わかりませんでした・・・。
      vcs: true
      # 一連のパスで指示されているディレクトリは無視するということかな?この辺よくわかりませんでした・・・。
      paths:
        - "/node_modules"
        - "/log"
        - "/tmp"

( ˘ω˘ )? 「multagen.ymlが何をしてくれているのか?」という疑問については、以下を参考にしまして、掴め(たような気に)ました。

以上で、ファイル共有の設定が完了しました。

以下の4つのファイルが準備できた段階で、ホストOS側での作業は終了です。

~/develop/vm/sample-pj
$ ls
# 実行結果↓
Dockerfile_node     docker-compose.yml
Vagrantfile     mutagen.yml

【後半戦:ゲストOS側での作業】

ここからは、VMを起動させてゲストOS側でReactの開発環境を作っていきます。

VagrantでVM起動

早速、VMの起動へ。

~/develop/vm/sample-pj(ホストOS内プロジェクトディレクトリ)
$ vagrant up
ディレクトリ内をチェーーーーーック( ·∀·)ノ
~/develop/vm/sample-pj(ホストOS内プロジェクトディレクトリ)
$ ls

# 実行結果↓
Dockerfile_node
Vagrantfile
docker-compose.yml
mutagen.yml
mutagen.yml.lock
ubuntu-xenial-16.04-cloudimg-console.log

作った覚えのない、ubuntu-xenial-16.04-cloudimg-console.logというファイルが新しくできていることがわかります。
( ˘ω˘ )? cloudimg-console.logって、何してくれるの?という疑問については、cloudimg-console.logとはを参考にしました。名前の前半のubuntu-xenial-16.04の部分は、仮想OSの種類に依るようです。

VMにssh接続

~/develop/vm/sample-pj(ホストOS内プロジェクトディレクトリ)
$ vagrant ssh

# 実行結果↓
Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.4.0-178-generic x86_64)
(略)
# Vagrantfileで指定したホスト名でターミナルが開く。
vagrant@sample-app:~$ 

vagrant@sample-app:~$ というように、ターミナルが表示されればOK。vagrantユーザーでsample-appというホスト(=ゲストOS)にログインされています。

VMの中身をチェーーーーーック( ·∀·)ノ
vagrant@sample-app
# /(ルートディレクトリ)配下にLinuxのディレクトリが並んでいます。
vagrant@sample-app:~$ cd /
vagrant@sample-app:/$ ls
# 実行結果↓
bin   home            lib64       opt   sbin  tmp      vmlinuz
boot  initrd.img      lost+found  proc  snap  usr      vmlinuz.old
dev   initrd.img.old  media       root  srv   vagrant
etc   lib             mnt         run   sys   var

仮想環境にゲストOSが導入されていることが確認できました。ちなみに、Linuxのディレクトリの構造についての参考URLはこちらLinuxのディレクトリ構造(一覧)を理解するを参照ください。

ホストOSとのフォルダ共有状況ををチェーーーーーック( ·∀·)ノ
vagrant@sample-app
# ~(ホームディレクトリ)
vagrant@sample-app:~$ cd 
vagrant@sample-app:~$ ls
# 実行結果↓
app


# appへ移動し、カレントディレクトリのパスを出力する
vagrant@sample-app:~/app$ pwd
# 実行結果↓ 
/home/vagrant/app #multagen.ymlファイルで指定したゲストOS側のエンドポイントと一致していることがわかります。


# appの中も見てみましょう。
vagrant@sample-app:~$ cd app
vagrant@sample-app:~/app$ ls
# 実行結果↓
Dockerfile_node     mutagen.yml
Vagrantfile         mutagen.yml.lock
docker-compose.yml  ubuntu-xenial-16.04-cloudimg-console.log

試しに、/app内でtestという名前でディレクトリを作成してみます。

vagrant@sample-app
# /app内でtestという名前でディレクトリを作成
vagrant@sample-app:~/app$ mkdir test
vagrant@sample-app:~/app$ ls

# 実行結果↓
Dockerfile_node
Vagrantfile
docker-compose.yml
mutagen.yml
mutagen.yml.lock
test  # 新しく作ったディレクトリ
ubuntu-xenial-16.04-cloudimg-console.log

一度、VMを離れて、ホストOS内の作業ディレクトリを見てみると、testという名前のファイルができているのが確認できました。

vagrant@sample-app
# exitでVMからログアウト
vagrant@sample-app:/vagrant$ exit

# 実行結果↓
logout
Connection to 127.0.0.1 closed.
~/develop/vm/sample-pj(ホストOS内プロジェクトディレクトリ)
$ ls

# 実行結果↓
Dockerfile_node
Vagrantfile
docker-compose.yml
mutagen.yml
mutagen.yml.lock
test # こちらにもtestディレクトリができています
ubuntu-xenial-16.04-cloudimg-console.log

# ファイルの共有が確認できたのでtestフォルダを削除します
$ rm -r test

# もう一度VMへssh接続
$ vagrant ssh

# 実行結果↓
Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.4.0-178-generic x86_64)
(略)

VM側でのtestディレクトリが消えているか確認します。

vagrant@sample-app
vagrant@sample-app:~$ cd app
vagrant@sample-app:~/app$ ls

# 実行結果↓ こちらでもtestファイルが無くなっていました。
Dockerfile_node     mutagen.yml
Vagrantfile         mutagen.yml.lock
docker-compose.yml  ubuntu-xenial-16.04-cloudimg-console.log

以上で、ホストOSとのフォルダ共有が確認できました。

dockerとdocker-compose動作も併せて、チェーーーーーック( ·∀·)ノ
vagrant@sample-app
# dockerの動作チェック
vagrant@sample-app:~$ docker --version
# 実行結果↓
Docker version 19.03.8, build afacb8b7f0

# docker-composeの動作チェック
vagrant@sample-app:~$ docker-compose --version
# 実行結果↓
docker-compose version 1.24.0, build 0aa59064

バージョン情報が表示されて、dockerとdocker-composeが導入されていることが確認できました。

Dockerコンテナの起動

vagrant@sample-app
# /appディレクトリにてコマンド実行。バックグラウンドでの実行するため-dオプションをつけます。
vagrant@sample-app:~/app$ docker-compose up -d

# コンテナの実行状況を確認しましょう
vagrant@sample-app:~/app$ docker-compose ps
# 実行結果↓
   Name             Command          State           Ports        
------------------------------------------------------------------
app_node_1   docker-entrypoint.sh    Up      0.0.0.0:3000->3000/tc

実行中のコンテナに入る

vagrant@sample-app
# 実行中のコンテナに入る。node部分は、docker-compose.ymlで指定したコンテナ名。
vagrant@sample-app:~/app$ $ docker-compose exec node sh
# 実行結果↓ 以下が表示されれば無事にコンテナ内に入れています。
/usr/src/app # 

コンテナ内でcreate-react-appのインストールとアプリのひな形作成

vagrant@sample-app
# creat-react-appのインストール
/usr/src/app # npm install -g create-react-app

# react-sampleという名前でアプリのひな形を作成
/usr/src/app # create-react-app react-sample

/usr/src/app # ls
# 実行結果↓
Dockerfile
Vagrantfile
docker-compose.yml
mutagen.yml
mutagen.yml.lock
react-sample # 新しいreactアプリが立ち上がっています
ubuntu-xenial-16.04-cloudimg-console.log

アプリの実行

vagrant@sample-app
# react-sampleディレクトリに移動
/usr/src/app # cd react-sample

# react-sampleを実行
/usr/src/app/react-sample # yarn start
# 実行結果↓
Compiled successfully!

You can now view react-sample in the browser.

  Local:            http://localhost:3000
  On Your Network:  http://172.18.0.2:3000

Note that the development build is not optimized.
To create a production build, use yarn build.

ゴォォォォォル(´∀`*)

ブラウザでhttp://localhost:3000 へアクセスしてみます。以下のような画面が出てくればOKです。

Screen Shot 2020-05-15 at 10.52.48.png

おまけ:再度コンテナに入る

一度コンテナを立ち上げた後、作業のためにコンテナに入るまでの手順はこちら。

# ホストOSの作業ディレクトリにて、VMを起動
ホストOS作業ディレクトリ $ vagrant ssh

# ゲストOSのreact-sampleアプリへ移動し、コンテナを実行
ゲストOS:~$ cd app
ゲストOS:~/app$ cd react-sample
ゲストOS:~/app/react-sample$ docker-compose up -d

# コンテナに入る
ゲストOS:~/app/react-sample$ docker-compose exec node sh

# コンテナ内
/usr/src/app #

ついでに、ソフトウェアの導入を確認。React.jsの開発ができる環境になっているようです。

/usr/src/app # node --version
v14.2.0
/usr/src/app # npm --version
6.14.4
/usr/src/app # yarn --version
1.22.4

以上!!

初・初・初学者です(´·ω·`)

暗中模索な感じで始めてしまい、うまくいかず途中で投げ出したくもなりましたが、なんとか動くところまで持ってこれました。多々、理解違いがあるかと思います。今後、間違いに気づいた点などは、適宜修正していこうと思います。

6
11
0

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
6
11