LoginSignup
41
43

More than 5 years have passed since last update.

Docker上でnginx + unicorn + mysql環境を構築

Posted at

はじめに

RailsアプリをEC2上のdockerで動かしてみます。以下、一台のホストに必要なコンテナsを載せるシングルホスト構成での作業です。ステージング環境のような非production用途を想定しています。

sc 2015-08-02 16.35.28.png

ミドルウェアは以下です。

  • Ruby 2.2.1
  • Rails 4.2.1
  • MySQL 5.6
  • nginx
  • unicorn

サンプルアプリのリポジトリは以下です
https://github.com/konpyu/rails-docker-sample

コンテナ構成はこんな感じです

  • nginxコンテナ
  • unicornコンテナ
  • mysqlコンテナ
  • データ共有コンテナ

sc 2015-08-02 16.24.37.png

ホストの起動と準備

EC2のインスタンスを適当に立てます。今回はCentOS7(ami-89634988)をホストOSとします。

# ログインしてrootになっておく
[centos@ip-10-0-x-xxx ~]$ sudo su -
[root@ip-10-0-x-xxx ~]#

gitとDockerをインストールしておきます

[root@ip-10-0-x-xxx ~]# yum -y install git docker
[root@ip-10-0-x-xxx ~]# docker -v
Docker version 1.6.2, build ba1f6c3/1.6.2

Dockerを起動します

[root@ip-10-0-x-xxx ~]# systemctl start docker

サンプルアプリをcloneしてきます

[root@ip-10-0-x-xxx ~]# mkdir /app
[root@ip-10-0-x-xxx ~]# cd /app
[root@ip-10-0-x-xxx app]# git clone https://github.com/konpyu/rails-docker-sample.git .
[root@ip-10-0-x-xxx app]# ls
app  bin  config  config.ru  db  docker  docker-compose.yml  Dockerfile  Gemfile  Gemfile.lock  lib  log  public  Rakefile  README.md  README.rdoc  vendor

appコンテナのビルド

Dockerfileでビルドします。RailsアプリのrootにDockefileを置いておけば、Railsのプロジェクトファイルをまるっとコンテナ内にCOPYできます。

Dockerfile
FROM ruby:2.2.1

RUN apt-get update && apt-get install -y nodejs mysql-client --no-install-recommends

# /appをコンテナ内のRails Appのディレクトリとする
RUN mkdir -p /app
WORKDIR /app

COPY Gemfile /app/
COPY Gemfile.lock /app/
RUN bundle install -j4 --without development test

COPY . /app

EXPOSE 3000
CMD ["bundle", "exec", "unicorn", "-c", "config/unicorn.rb"]
[root@ip-10-0-x-xxx app]# docker build -t todo/app .

MySQL, nginx, datastore用コンテナの起動

次にコンテナ間のファイル共有専用のデータストアコンテナと、DB用コンテナ、リバプロ用コンテナを起動します

まずは、コンテナ間でデータを共有するために、busyboxをベースに起動します。今回は、このコンテナ内にunicorn用のソケットを置いてコンテナ間で共有します

[root@ip-10-0-x-xxx app]# docker run -i -t -d -P --name data -v /share busybox /bin/sh

次に、MySQLの公式イメージを使ってDBコンテナを立てます。サンプルアプリ内の#{Rails.root}/docker/mysql/my.cnfを設定ファイルとして注入しておきます

SELinuxを止めておきます (参考)

chcon -Rt svirt_sandbox_file_t /app/docker
[root@ip-10-0-x-xxx app]# docker run --name mysql -e MYSQL_ROOT_PASSWORD=test -v /app/docker/mysql:/etc/mysql/conf.d -d mysql:5.6

my.cnfはこんな感じです

#{Rails.root}/docker/mysql/my.cnf
[mysqld]
innodb_strict_mode
innodb_file_format = Barracuda
innodb_file_per_table
innodb_large_prefix = 1

リバプロ(nginx)のコンテナを公式イメージから立てます。unicornのsocketは先ほど立ててたbusyboxの中の/share/unicorn.sock に置くものとします

#{Rails.root}/docker/nginx/nginx.conf
upstream unicorn_server {
   server unix:/share/unicorn.sock;
}

server {
    listen       8080;
    root         /app/public;

    location / {
        if (!-f $request_filename) {
            proxy_pass http://unicorn_server;
            break;
        }
    }
}

nginxのコンテナを起動します

[root@ip-10-0-x-xxx app]# docker run --name nginx -p 80:8080 -v /app/docker/nginx/nginx.conf:/etc/nginx/conf.d/nginx.conf:ro --volumes-from data  -d nginx

ここまでの段階で、ブラウザでアクセスすると502(Bad Gateway)が返ってくるはずです

最後に、unicornを立てて、nginxに来たアクセスをunicornにproxyしましょう

[root@ip-10-0-x-xxx app]# docker run --name unicorn --volumes-from data -e RAILS_ENV=production -e SECRET_KEY_BASE=ageman --link mysql:db -d todo/app

DBを作成します

[root@ip-10-0-x-xxx app]# docker exec -it unicorn bundle exec rake db:create

これで準備完了。ブラウザで見ると、TOPに表示されるはずです

sc 2015-08-02 14.47.47.png

今後の検討事項

本ポストは見通しを良くするために色々省略しています。シンプルなシングルホスト環境でも、以下にあげた事項は検討の価値/必要がアリです

  • docker-composeでの起動
  • Blue-Green デプロイ
  • ディスクIOの最適化
  • ログ収集
  • rootを使わない
41
43
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
41
43