7年前に書いたRuby 1.8 + Rails 1.2.6 + MySQL 5.0のアプリがあり、ほとんど使ってないけど、たま~に使うので、扱いに困っていました。
そこで、今動いているミドルウェアのバージョンをそのままにDockerでコンテナ化して、どんな環境にも移動できるようにしました。これでどこでも昔のバージョンのまま動き続けることができる、いわるゆ塩漬けです!
それを紹介します。
Dockerの実行環境
- CentOS Linux release 7.1.1503
- Docker version 1.10.3, build 3999ccb-unsupported
塩漬け対象アプリの構成
- ミドル
- Ruby1.8.7
- Ruby on Rails 1.2.6
- MySQL 5.0.77
- アプリ
- bitbucketにあるレポジトリを/usr/local/myappにcloneして動作させる
- データ
- MySQLにあるデータベースの中のテーブル一式
DBのコンテナ化
Dockerfileの準備
MySQLの公式には5.0のイメージはなかったため、lsdriscollさんを参考にしつつ公式のCentOS 5.11のイメージをベースに自分で作ることにしました。
ファイル構成
└ myapp-db
├ Dockerfile
├ initial.sql
└ my.cnf
Dockerfileの内容
FROM centos:5.11
MAINTAINER fetaro@xxx.com
RUN yum -y install mysql-server-5.0.95-5.el5_9
COPY my.cnf /etc/my.cnf
COPY initial.sql /initial.sql
RUN mysql_install_db --datadir=/var/lib/mysql --user=mysql
USER root
CMD ["mysqld_safe", "--init-file=/initial.sql", "--user=mysql"]
initial.sqlの内容
GRANT ALL PRIVILEGES ON *.* to root@'localhost' IDENTIFIED BY 'xxxx' WITH GRANT OPTION;
GRANT ALL PRIVILEGES ON myapp_production.* to myapp@'%' IDENTIFIED BY 'xxx';
GRANT ALL PRIVILEGES ON myapp_production.* to myapp@'localhost' IDENTIFIED BY 'xxx';
FLUSH PRIVILEGES;
CREATE DATABASE IF NOT EXISTS myapp_production DEFAULT CHARACTER SET utf8;
(以降テーブルの作成など)
my.cnfの内容
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
old_passwords=0
[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
port=3306
イメージのビルド
Dockerfileのあるディレクトリで
docker build -t fetaro/myapp-db .
-t はイメージの名前指定。「DockerHubのユーザ名/」を頭につけるのが作法っぽいです。
確認
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
fetaro/myapp-db latest 2af6e1f44b8c 32 minutes ago 381.3 MB
docker.io/centos 5.11 b424fba01172 4 months ago 284.1 MB
ベースになっているcentosと自分で作ったmyapp-dbが見えます。
コンテナの生成&起動
docker run --name myapp-db -d fetaro/myapp-db
確認
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
767b41356fa6 fetaro/myapp-db "mysqld_safe --init-f" 33 minutes ago Up 33 minutes myapp-db
このMySQLはポート指定していないため、外部からはアクセスできません。
しかし、Dockerのリンク機能を使って、次に作るWebアプリコンテナとリンクを結び、Docker内部で通信するようにするため問題ありません。
Webアプリのコンテナ化
Dockerfileの準備
ruby 1.8.7が動くベースイメージをDocker Hubから探し、docker.io/nvulane/ruby1.8.7を採用することにしました。
ファイル構成
└ myapp-web
└ Dockerfile
Dockerfileの内容
FROM docker.io/nvulane/ruby1.8.7
MAINTAINER fetaro@xxxx.com
WORKDIR /usr/local/
RUN apt-get install -y
RUN gem install rake -v 0.8.7 --no-ri --no-rdoc
RUN gem install rails -v 1.2.6 --no-ri --no-rdoc
# アプリをbitbucketから取得して/usr/local/myappに展開(一行で書くのが作法)
RUN wget --no-check-certificate https://fetaro:xxxxxx@bitbucket.org/fetaro/myapp/get/master.zip \
&& unzip master.zip -d tmp \
&& mv tmp/* myapp \
&& rm -f master.zip
# 起動する時にプロジェクトホームにいる必要があるので移動
WORKDIR /usr/local/myapp/
CMD ["ruby", "script/server", "-e", "production"]
EXPOSE 3000
ポイントとして、Dockerは1コマンドごとにファイルシステムの差分を管理していくので、まとめて作業する場合はRUNを何行も書くのではなく1行で書くのが作法とのこと。そのためgitからアプリ取得して展開するところは1行で書いています。
イメージのビルド
Dockerfileのあるディレクトリで
docker build -t fetaro/myapp-web .
-tはイメージに名前を付けている。
確認
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
fetaro/myapp-db latest 2af6e1f44b8c 37 minutes ago 381.3 MB
fetaro/myapp-web latest abc6e670ee65 About an hour ago 488.9 MB
docker.io/centos 5.11 b424fba01172 4 months ago 284.1 MB
docker.io/nvulane/ruby1.8.7 latest b9b3d6f40baf 5 months ago 451.8 MB
新たにruby1.8.7のイメージとmyapp-webのイメージができていることがわかる。
コンテナの作成&起動
docker run --name myapp-web -d -p 3000:3000 -t --link myapp-db:myapp-db fetaro/myapp-web
ポイントは--linkにてmyapp-dbコンテナとリンクしているところ。これによりmyapp-webコンテナの/etc/hosts
に myapp-dbのエントリが追加され、アプリからはmyapp-db
というホスト名で接続できます。
確認
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6c40992e1373 fetaro/myapp-web "ruby script/server -" 36 minutes ago Up 36 minutes 0.0.0.0:3000->3000/tcp myapp-web
767b41356fa6 fetaro/myapp-db "mysqld_safe --init-f" 38 minutes ago Up 38 minutes myapp-db
myapp-webとmyapp-dbが起動していることが分かります。
これで完成!ポート3000にアクセスすればアプリが使えます。
さいごに
この構成では、データの更新はmyapp-dbコンテナの中を直接更新する作りになっているため、コンテナを壊すと更新したデータは消えます。今回は塩漬けアプリでほとんど更新が無いためこの方式を採用していますが、データを外出ししたい場合はdockerのボリュームやデータコンテナを使うほうがよいでしょう。
また、docker compose等を使って二つのコンテナをまとめて管理したほうがよいらしいですが、次回以降のテーマとします。
あと、実行ユーザがかなり適当でrootでwebを動かしているので、これは変えたほうが良いさそうですが、めんどうなのでこのままで。
Docker初心者なので、いろいろ間違っているかもしれません。ツッコミ等があればどしどし下さい m(_ _)m