以前、sameersbn/redmineというRedmineのイメージを試してみましたが、アプリケーションとMySQLでコンテナを分離した場合、複数のコンテナ起動や、DBの作成、マイグレーションの実行が個別に必要となり手間がかかっていました。
そこで今回は、マルチコンテナ構成ツールであるFigを用いて、アプリケーションとMySQLでコンテナを分離した場合でも、Redmineを一括起動するDockerfileを書いてみました。
構成
- Ubuntu 14.04
- Docker 1.0.0
- Fig 0.5.2
コンテナとDockerfileの割り振り
Redmineの起動のためには、DBサーバ、アプリケーションサーバ、Webサーバが必要となります。これらを1つのコンテナの中で動かす事も出来ますが、安定性等を考え、以下のように2つのコンテナで動かす事にします。
また、Dockerfileのメンテナンス性を考え、APコンテナはRubyまでを導入したイメージと、そのイメージをベースにRedmineを導入したイメージに分離させています。Redmineの設定を変更したい場合、Rubyのインストールを省くことができます。
Dockerfile
Dockerfileを以下のように作成します。
ソースコードはこちら@githubで公開しています。
Dockerfileの構成
Dockerfileの構成は以下の通りです。
このほかにもコンテナに追加する定義ファイルもいくつかあります。
fig-redmine ├──fig.yml ... Figのコンテナ起動定義ファイル ├──mysql │ └──Dockerfile ... MySQL用のDockerfile ├──ruby │ └──Dockerfile ... Ruby用のDockerfile └──redmine └──Dockerfile ... Redmine用のDockerfile
MySQL
$ vi mysql/Dockerfile FROM ubuntu:14.04 MAINTAINER hidemium # install basic package ADD sources.list /etc/apt/sources.list ENV DEBIAN_FRONTEND noninteractive RUN apt-get update && \ apt-get -y install \ mysql-server \ openssh-server \ supervisor && \ apt-get clean # root user RUN echo 'root:root' | chpasswd # install sshd RUN mkdir -p /root/.ssh /var/run/sshd ADD id_rsa.pub /root/.ssh/authorized_keys RUN chmod 700 /root/.ssh RUN chmod 600 /root/.ssh/authorized_keys RUN sed -ri 's/UsePAM yes/#UsePAM yes/g' /etc/ssh/sshd_config RUN sed -ri 's/#UsePAM no/UsePAM no/g' /etc/ssh/sshd_config RUN sed -ri 's/PermitRootLogin without-password/PermitRootLogin yes/g' /etc/ssh/sshd_config # config supervisor RUN mkdir -p /var/log/supervisor /etc/supervisor/conf.d ADD mysqld.conf /etc/supervisor/conf.d/mysqld.conf ADD sshd.conf /etc/supervisor/conf.d/sshd.conf # install MySQL RUN rm -rf /var/lib/mysql/mysql RUN rm -rf /var/lib/apt/lists/* ADD my.cnf /etc/mysql/my.cnf ADD mysql-listen.cnf /etc/mysql/conf.d/mysql-listen.cnf RUN chown -R mysql:mysql /var/lib/mysql RUN chmod 700 /var/lib/mysql # initialize MySQL RUN mysql_install_db --user mysql > /dev/null RUN /usr/bin/mysqld_safe & \ sleep 3 && \ mysqladmin -u root password "root" && \ mysql -u root -proot -e "GRANT ALL ON *.* TO 'root'@'172.17.%.%' IDENTIFIED BY '' WITH GRANT OPTION;" && \ mysql -u root -proot -e "CREATE USER 'redmine'@'%.%.%.%' IDENTIFIED BY 'redmine';" && \ mysql -u root -proot -e "CREATE DATABASE IF NOT EXISTS redmine_production DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;" && \ mysql -u root -proot -e "GRANT ALL PRIVILEGES ON redmine_production.* TO 'redmine'@'%.%.%.%';" && \ mysql -u root -proot -e "FLUSH PRIVILEGES;" # expose ports EXPOSE 22 3306 # define default command. CMD ["supervisord", "-n"]
Ruby
$ vi ruby/Dockerfile FROM ubuntu:14.04 MAINTAINER hidemium # install basic package ADD sources.list /etc/apt/sources.list ENV DEBIAN_FRONTEND noninteractive RUN apt-get update && \ apt-get -y install \ openssh-server \ supervisor \ build-essential \ curl \ unzip \ git-core \ subversion \ mercurial \ libcurl4-openssl-dev \ libreadline-dev \ libssl-dev \ libxml2-dev \ libxslt1-dev \ libyaml-dev \ zlib1g-dev && \ apt-get clean && \ curl -O http://ftp.ruby-lang.org/pub/ruby/2.1/ruby-2.1.2.tar.gz && \ tar -zxvf ruby-2.1.2.tar.gz && \ cd ruby-2.1.2 && \ ./configure --disable-install-doc && \ make && \ make install && \ cd .. && \ rm -r ruby-2.1.2 ruby-2.1.2.tar.gz && \ echo 'gem: --no-document' > /usr/local/etc/gemrc # root user RUN echo 'root:root' | chpasswd # install sshd RUN mkdir -p /root/.ssh /var/run/sshd ADD id_rsa.pub /root/.ssh/authorized_keys RUN chmod 700 /root/.ssh RUN chmod 600 /root/.ssh/authorized_keys RUN sed -ri 's/UsePAM yes/#UsePAM yes/g' /etc/ssh/sshd_config RUN sed -ri 's/#UsePAM no/UsePAM no/g' /etc/ssh/sshd_config RUN sed -ri 's/PermitRootLogin without-password/PermitRootLogin yes/g' /etc/ssh/sshd_config # install supervisor RUN mkdir -p /var/log/supervisor /etc/supervisor/conf.d ADD sshd.conf /etc/supervisor/conf.d/sshd.conf # install bundler RUN \ echo 'gem: --no-rdoc --no-ri' >> /.gemrc && \ gem install bundler
Redmine
$ vi redmine/Dockerfile FROM ubuntu-ruby:14.04 MAINTAINER hidemium ENV REDMINE_VERSION 2.5-stable ENV REDMINE_HOME /var/redmine ENV SETUP_DIR /app/setup ENV RAILS_ENV production # install basic package RUN apt-get update && \ apt-get -y install \ nginx \ imagemagick \ libmagickcore-dev \ libmagickwand-dev \ libmysqlclient-dev # install Redmine RUN git clone -b ${REDMINE_VERSION} https://github.com/redmine/redmine.git ${REDMINE_HOME} WORKDIR /var/redmine RUN echo 'gem "mysql2", "~> 0.3.11"' >> Gemfile RUN echo 'gem "unicorn"' >> Gemfile RUN bash -l -c 'bundle install --without development test' # install plugins RUN mkdir -p ${SETUP_DIR} ADD setup/themes_install ${SETUP_DIR}/themes_install ADD setup/plugins_install ${SETUP_DIR}/plugins_install RUN chmod 755 ${SETUP_DIR}/* RUN ${SETUP_DIR}/themes_install RUN ${SETUP_DIR}/plugins_install # add config file ADD config/database.yml ${REDMINE_HOME}/config/database.yml ADD config/configuration.yml ${REDMINE_HOME}/config/configuration.yml ADD config/unicorn.rb ${REDMINE_HOME}/config/unicorn.rb RUN mkdir ${REDMINE_HOME}/public/plugin_assets # install nginx ADD redmine.conf /etc/nginx/conf.d/redmine.conf RUN rm -f /etc/nginx/sites-enabled/default RUN ln -s /etc/nginx/sites-available/redmine /etc/nginx/sites-enabled/redmine RUN echo "daemon off;" >> /etc/nginx/nginx.conf # add supervisor config file ADD unicorn.conf /etc/supervisor/conf.d/unicorn.conf ADD nginx.conf /etc/supervisor/conf.d/nginx.conf # expose ports EXPOSE 22 80 # define default command CMD bash -l -c 'bundle install --without development test' && \ bash -l -c 'bundle exec rake generate_secret_token' && \ mv plugins plugins-1 && \ bash -l -c 'bundle exec rake db:migrate RAILS_ENV=${RAILS_ENV}' && \ mv plugins-1 plugins && \ bash -l -c 'bundle exec rake redmine:plugins:migrate RAILS_ENV=${RAILS_ENV}' && \ supervisord -n
- 「FROM ubuntu-ruby:14.04」で先に作成したRubyイメージをベースにしています。
- RedmineのソースコードをGitHubのリポジトリから取得しています。
- 一度bundle installすれば、Dockerのキャッシュが使われるので再実行が短縮できます。そのため、最初にbundle installを実行しています。ただし、RedmineのGemfileは、database.yml内の情報からデータベースの種類を判別し、必要なgemを選択しています。database.ymlを先に追加すると処理が失敗するため、「'gem "mysql2", "~> 0.3.11"' >> Gemfile」で追加しています。
- テーマとプラグインのインストールは、「themes_install」と「plugins_install」というシェルから実行しています。
- RedmineをNginx + Unicornで動作させる設定を行っています。
- CMDでマイグレーションコマンドを定義することで、Redmineコンテナ起動時にマイグレーションを自動で行うことができます。
Dockerfileのビルド
以下のコマンドにより、Dockerfileの取得とDockerイメージのビルドを行います。
$ git clone https://github.com/hideakihal/docker-fig-redmine.git $ cd docker-fig-redmine $ sudo docker build -t ubuntu-mysql:14.04 mysql $ sudo docker build -t ubuntu-ruby:14.04 ruby $ sudo docker build -t ubuntu-redmine:14.04 redmine
Fig
Dockerイメージの用意ができたため、ここからはFigを使用方法を説明します。
インストール
FigはPythonで書かれているので、パッケージ管理をするpipをインストールしておきます。pipを使ってFigをインストールします。
$ sudo apt-get install -y python-pip python2.7-dev $ sudo pip install -U fig
fig.yml
複数のコンテナをどのように起動するかはfig.ymlというファイルで定義します。
fig.ymlは、以下のような構成になり、起動するDockerイメージやポート番号、コンテナ間通信の設定などが行えます。
fig.ymlのリファレンスは公式サイトにあります。
$ vi fig.yml db: image: ubuntu-mysql:14.04 ports: - 22 - 3306 web: image: ubuntu-redmine:14.04 ports: - 22 - 80 environment: - DB_HOST=db_1 links: - db
上記の設定を通常のDockerコマンドで表現すると以下のようになります。
毎回以下のようなコマンドを打つのは大変なので、とても簡単できるようになります。
$ sudo docker run -d -p 22 -p 3306 --name figredmine_db_1 ubuntu-mysql:14.04 $ sudo docker run -d -p 22 -p 80 -e "DB_HOST=db_1" --link figredmine_db_1:db_1 --name figredmine_web_1 ubuntu-redmine:14.04
環境変数について
fig.yml内で、DB_HOSTという環境変数を定義しています。これは、APコンテナのdatabase.ymlにDBコンテナをホスト名を渡すために行っています。
当初は、以下のようにlinkオプションの起動でDBコンテナのIPアドレスを取得していましたが、DBコンテナ名が変わるとDockerイメージのリビルドが必要でした。
$ vi /var/redmine/config/database.yml production: adapter: mysql2 database: redmine_production host: <%= ENV.fetch('DB_1_PORT_3306_TCP_ADDR') %> port: <%= ENV.fetch('DB_1_PORT_3306_TCP_PORT') %>
Figのissueを見てみると、linkオプションにより/etc/hostsも変更されることが分かり、以下のように設定を修正しました。
$ vi /var/redmine/config/database.yml production: adapter: mysql2 database: redmine_production host: <%= ENV.fetch('DB_HOST') %> port: 3306 ...
Dockerの公式ドキュメントを見てみると、コンテナのポート番号やIPをもった環境変数と/etc/hostsが追加されることが記載されています。
実際のコンテナでも確認したところ、確かにコンテナの環境変数と/etc/hostsが更新されていることが分かりました。
root@be9520e48d64:~# env DB_1_PORT_3306_TCP_ADDR=172.17.3.117 DB_1_PORT_3306_TCP_PORT=3306 ...
ホスト名が、db_1のように「コンテナ名_数字」となっていますが、これはFigの仕様で同じDockerイメージをスケールさせる場合に末尾の数字がカウントアップされていきます。今回はスケールさせないため、末尾の数字は1として表示されます。
root@be9520e48d64:~# cat /etc/hosts 172.17.3.117 db_1 172.17.3.117 figredmine_db_1 ...
複数コンテナの一括起動
以下のコマンドを実行し、複数コンテナを一括起動します。
$ sudo fig up -d
起動の進捗を確認する場合は、以下のコマンドを使用できます。
$ sudo fig logs Attaching to figredmine_db_1, figredmine_web_1 web_1 | Don't run Bundler as root. Bundler can ask for sudo if it is needed, and web_1 | installing your bundle as root will break this application for all non-root web_1 | users on this machine. web_1 | Your Gemfile lists the gem vcard (~> 0.2.8) more than once. web_1 | You should probably keep only one of them. web_1 | While it's not a problem now, it could cause errors if you change the version of just one of them later. web_1 | Your Gemfile lists the gem capybara (~> 2.1.0) more than once. web_1 | You should probably keep only one of them. web_1 | While it's not a problem now, it could cause errors if you change the version of just one of them later. ...
コンテナの起動を確認する場合、以下のコマンドを使用できます。APとDBのコンテナが起動していることが分かります。
docker psコマンドより情報がまとまってシンプルに表示できます。
$ sudo fig ps Name Command State Ports --------------------------------------------------------------------------------------- figredmine_db_1 supervisord -n Up 49177->22/tcp, 49178->3306/tcp figredmine_web_1 /bin/sh -c bash -l -c '... Up 49179->22/tcp, 49180->80/tcp
上記で、80番ポートにフォワードされているポート番号を確認し、ブラウザから、「http://localhost:ポート番号」にアクセスし、Redmineのログイン画面が表示されることを確認します。
本番環境で動作させる場合
fig upコマンドを再実行すると、既存のコンテナは削除され、コンテナが再作成されます。開発中は不要なコンテナの削除を自動的に行ってくれるため便利ですが、本番環境で現行のコンテナを残して、Blue-Green Deploymentを行いたい場合は不便です。また、開発環境と本番環境でコンテナの起動設定を変えたい場合などがあるかと思います。
そこで、fig upコマンドでは、-fオプションによりデフォルトパスのfig.yml以外のfig.ymlを指定することができます。
以下のように、fig-production.yml(任意)を作成します。
上記のfig.ymlとは異なり、コンテナ名の変更や、データの永続性のため共有ディレクトリの設定を追加しています。また、DB_HOSTのコンテナ名も合わせて変更します。
$ vi fig-production.yml dbBlue: image: ubuntu-mysql:14.04 ports: - 22 - 3306 volumes: - /path/in/host:/var/lib/mysql webBlue: image: ubuntu-redmine:14.04 ports: - 22 - 80 environment: - DB_HOST=dbBlue_1 volumes: - /path/in/host:/var/redmine/files links: - dbBlue
- コンテナ名は記号は不可で、英数字しか使用できないようです。
以下のコマンドを実行し、本番環境用のコンテナを起動します。
$ sudo fig -f fig-production.yml up -d