はじめに
IDEを使う場合やデザイナさんのPCで開発をする場合にもDockerで手軽に開発環境を作りたい。
Docker+Virtualboxを使用するとコンテナとホストOSの間に簡単に共有フォルダが作れるので、
好きなエディタなどを使って開発を進めることができます。
環境
- DockerToolbox 1.9.1
https://www.docker.com/products/docker-toolbox
インストーラをダウンロードして、インストールを進めるとGit, Dockerなど開発に必要なツール一式がまとめて入ります。
ファイル構成
適当な場所に開発環境用ディレクトリを用意します。
+ source
- Dockerfile
+ app
- Gemfile
- index.rb
FROM ruby
RUN mkdir -p /srv/www/app
COPY app/Gemfile /srv/www/app
WORKDIR /srv/www/app
RUN bundle install
CMD ruby index.rb
source "http://rubygems.org"
gem 'sinatra'
gem 'sinatra-contrib'
require 'sinatra'
require 'sinatra/reloader'
set :bind, '0.0.0.0'
set :port, 3000
get '/' do
'hello'
end
Dockerイメージ作成
DockerToolboxをインストールした時に入った、「Docker Qickstart Terminal」を起動します。
初回起動時は仮想マシンの作成が入るので少し時間が掛かります。
ターミナルの起動が完了したら、先ほど作ったフォルダに移動してDockerイメージを作成します。
(Cドライブへの移動は小文字のcなので注意)
$ cd /c/source
$ docker build -t web .
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
web latest a8b38a36ca7d About a minute ago 725.5 MB
Dockerイメージの起動
作成したイメージを起動します。
WindowsのGitBashの場合は / スラッシュを前に付けないとうまく動かないようです。
$ cd /c/source/app
$ docker run -d -v /$(pwd):/srv/www/app -p 3000:3000 -t web
起動したイメージにアクセスしてみる
仮想マシンのIPを確認します。
$ docker-machine ip default
192.168.99.100
http://192.168.99.100:3000/ へアクセスして確認する
ファイルを変更してみる
source/app/index.rbの中身を変更して反映されるか確認してみる。
require 'sinatra'
require 'sinatra/reloader'
set :bind, '0.0.0.0'
set :port, 3000
get '/' do
'hello world'
end
保存するとすぐに反映されているのがわかります。
このぐらいすぐに反映されるのであれば実際の開発で十分使用できると思います。
さらに複雑な構成
実際の開発ではMySQLやNginxも含まれる構成が一般的です。
docker-composeを使って一括でコンテナの起動ができるようにします。
今回作成する構成は上図の様になっています。RubyプロセスがMySQLとNgnixと通信する形になります。
ファイル構成
webに先ほど作った簡易版の構成をそのまま入れます。
注意するのはweb以下にappを配置しないとDockerイメージの構築に失敗してしまいます。
+ source
- docker-compose.yml
+ web
- Dockerfile
+ app
- Gemfile
- index.rb
+ ngnix
- Dockerfile
- nginx.conf
web:
build: ./web
volumes:
- ./web/app:/srv/www/app
links:
- mysql
datastore:
image: busybox
volumes:
- /data/nginx
- /var/lib/mysql
nginx:
build: ./nginx
ports:
- '80:80'
volumes_from:
- datastore
links:
- web
mysql:
image: mysql
environment:
MYSQL_ROOT_PASSWORD: 'hoge'
volumes_from:
- datastore
MySQLのデータはDockerコンテナを終了すると消えてしまうので、専用のデータ永続化用のコンテナを用意します。
データだけ入れればいいのでbusyboxみたいな小規模を利用します。
FROM ruby
RUN apt-get update && apt-get -y install mysql-client
RUN mkdir -p /srv/www/app
COPY app/Gemfile /srv/www/app
WORKDIR /srv/www/app
RUN bundle install
CMD ruby index.rb
先ほどと違うのはRubyでMySQLと接続するためmysql-clientをインストールする必要がある点です。
source "https://rubygems.org"
gem 'sinatra'
gem 'sinatra-contrib'
gem 'mysql2'
MySQL接続用ライブラリをインストールするようにします。
require 'sinatra'
require 'sinatra/reloader'
require 'mysql2'
set :bind, '0.0.0.0'
set :port, '3000'
# MySQL接続
client = Mysql2::Client.new(
:host => ENV['MYSQL_PORT_3306_TCP_ADDR'],
:username => 'root',
:password => ENV['MYSQL_ENV_MYSQL_ROOT_PASSWORD']
)
get '/' do
results = client.query("SHOW DATABASES")
tables = []
results.each do |row|
tables << row['Database']
end
"#{tables.join('<br>')}"
end
MySQLとの接続確認用の処理を追加しています。
FROM nginx
COPY nginx.conf /etc/nginx/nginx.conf
Nginx設定ファイルを反映するためにビルドファイルを用意してからイメージ作成を行います。
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
sendfile on;
keepalive_timeout 65;
access_log /data/nginx/access.log main;
upstream backend {
server web:3000;
}
server {
listen 80;
server_name localhost;
location / {
if (-f $request_filename) { break; }
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://backend;
}
}
include /etc/nginx/conf.d/*.conf;
}
SinatraアプリのTPC:3000番ポートを80番ポートに流すように設定を行います。
docker-compose.yml に link: web という名前で設定したので、
host名にwebという名前を使用することが出来るようになっています。
Docker Composeによるイメージの起動
先ほど作ったのとは別環境ということを想定して、新しく仮想環境を作るとこから始めます。
docker-machine の createオプションを利用してdevという名前の環境を作ります。
evalコマンドを利用すると環境設定を読み込んでdockerコマンドなどが使えるようになります。
$ cd /c/source
$ docker-machine create --driver virtualbox dev
$ eval "$(docker-machine env dev)"
$ docker-compose build
$ docker-compose up
docker-composeコマンドを利用してイメージのビルドと起動をします。
アクセスしてみる
先ほどと同じくIPの確認をしてから、ブラウザでアクセス。
$ docker-machine ip dev
192.168.99.100
http://192.168.99.100/ へアクセスして確認
Docker環境構築をバッチ化
構築は2,3コマンドを叩くだけで作成できるようになりましたが、デザイナさんに毎回コマンドを叩いてもらうのは敷居が高いですね。
Windowsなのでバッチファイルを作成して、デスクトップなどに置いてもらって起動するだけで環境が立ち上がるようにしてみます。
#!/bin/sh
docker-machine create --driver virtualbox dev
docker-machine start dev
eval "$(docker-machine env dev)"
docker-compose build
docker-compose up -d
先ほど作ったDocker構成のルート(docker-compose.ymlがある)に上記のバッチファイルを置きます。
ファイルの拡張子をshにしておくと、GitBashの関連付けファイルとなっているため、後はファイルをダブルクリックするだけで起動します。
上記のファイルは起動用なので、終了用など適宜用意しておくと便利です。
おわりに
Docker+Virtualboxでは自動で共有フォルダを作ってくれるので、Dockerコンテナ起動にvolumeを指定するだけで、ホストOS側の好き場所のフォルダをコンテナ上に展開して、ファイルの編集ができます。
環境構築を簡易にして気持よく開発をしてもらえるようにしたいですね。