Docker Image とは
Docker Image とはDockerが動作するホストであれば動作することの出来る、Docker コンテナを実行するパッケージをまとめたものです。例えばコンテナをVMの様に扱い、コンテナの中から環境を構築してそれをDocker Image ファイルとして書き出します。するとそのファイルを転送すればいつでも環境を再構築することが可能になります。
今回はCentOS上でRubyOnRailsのコンテナを構築し、それをDocker Image に固めたいと思います。これ系の記事はQeetaにたくさんあるのですが、ほとんどがMac上での方法でCentOS上での方法を解説した記事がありませんでした。固めたDocker Image 自体はどちらでも動くと思うのですが、Mac上でのDocker Image の固め方がCentOSでは上手くいかなかったのです。
準備
最新版のDockerとdocker-composeをインストールします。バージョンが古いと失敗することがあります。
諸々の必要なパッケージをインストール
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
リポジトリを追加
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
Docker CEをインストール
sudo yum install -y docker-ce
sudo systemctl start docker
sudo curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
手順1
Dockerfileを作成します。CentOSをVMの様に使います。
$ cat Dockerfile
FROM centos:7
# update
RUN yum -y update && yum clean all
# set locale
RUN yum reinstall -y glibc-common && yum clean all
RUN localedef -f UTF-8 -i ja_JP ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8
RUN unlink /etc/localtime
RUN ln -s /usr/share/zoneinfo/Japan /etc/localtime
# editor install
RUN yum install -y vim && yum clean all
docker-compose.ymlを作成する。DBにはMySQL8.0を使用します。
$ cat docker-compose.yml
version: '3'
services:
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: password
ports:
- '3306:3306'
command: --default-authentication-plugin=mysql_native_password
volumes:
- mysql-data:/var/lib/mysql
centos:
build: .
volumes:
- .:/myapp
ports:
- "3000:3000"
depends_on:
- db
stdin_open: true
tty: true
volumes:
mysql-data:
driver: local
コンテナ起動。
docker-compose up -d
以上でCentOS7コンテナとDBコンテナを作成しました。次からはRailsの環境をCentOS7コンテナに入って作成していきます。尚、DBコンテナのDocker Imageエクスポートに関してはこの後触れることはないので、この時点で実施しても構わないのですが、後でまとめてやる事にします。
手順2
基本的には以前書いたRails環境構築の記事の通りです。まずはrbenv
をインストールします。
yum update -y
yum install -y git
yum install -y bzip2 gcc openssl-devel readline-devel zlib-devel make
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
git clone git://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
パスを通します。
# vi /root/.bashrc
export PATH="$PATH:/root/.rbenv/bin"
eval "$(rbenv init -)"
# source /root/.bashrc
# rbenv -v
rbenv 1.1.2-30-gc879cb0
Ruby
をインストールします。
# rbenv install 2.7.1
# rbenv global 2.7.1
# ruby -v
ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-linux]
Rails
をインストールします。
# gem install bundler
# bundle init
# gem install rails
いつものパッケージ群
# yum -y install gcc-c++
# gem install sassc -v 2.4.0
# yum -y install epel-release
# curl -sL https://rpm.nodesource.com/setup_14.x | bash -
# yum -y install nodejs
# npm install -g yarn
MySQLパッケージをインストールする。
railsとmysqlを繋ぐmysql2をインストールするのに必要なもの
# yum install -y mysql-devel
Railsプロジェクトを作成する。
プロジェクト作成。「bundle install」は後で、データベースはmysqlを指定
# rails new labo --database=mysql --skip-bundle --skip-test --skip-active-storage
# cd labo
# bundle install
config/database.yml
を編集。ホスト名はdocker inspect コンテナID
で取得。
# cat config/database.yml
default: &default
adapter: mysql2
encoding: utf8mb4
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: root
password: password
host: 172.18.0.2
※一部抜粋
DBを作成する。
# rails db:create
Created database 'labo_development'
Created database 'labo_test'
# rails webpacker:install
# rails server -b 0.0.0.0
これでRailsの環境を作成できました。次はようやくイメージに書き出します。
Docker Image 書き出し
いよいよ「コンテナからイメージを作成→イメージをファイルに書き出し」という手順を解説していきます。
コンテナを元にイメージを作成する
# docker commit -m "MySQL8.0 Image" 【mysqlのコンテナID】 イメージ名
# docker commit -m "Rails6.0 Image" 【railsのコンテナID】 イメージ名
イメージが追加されます
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
rails6 latest 93cd214aa574 32 seconds ago 1.18GB
mysql8 latest 107b24c47d66 3 minutes ago 544MB
イメージをファイルに書き出します
# docker save rails6 > rails6.tar
# docker save mysql8 > mysql8.tar
# ls
Dockerfile docker-compose.yml mysql8.tar rails6.tar
書き出したファイルは次の方法でインポート可能です。
# docker load < mysql8.tar
# docker load < rails6.tar
# docker images
下記のコマンドで起動すれば先ほどのrails環境を再現する事ができ、すぐに開発を始められます。
# docker run -d -p 3006:3006 --name mysql mysql8
# docker run -itd -p 3000:3000 --name rails rails6
以上です。
終わりに
Qeetaなどの記事ではDockerfileまで落とし込んで、「これを実行すれば動きます」みたいな手法がほとんどでした。恐らくそれがベストプラクティスだと思います。サーバは常に最小構成が理想なので、コンテナにも同様の事が言えます。しかしVMの様にコンテナを扱える事もDockerの強みです。上手くいかなければ簡単に掃除出来ますし、完成したらイメージファイルに書き出すだけで再利用が可能です。
要約するとわざわざQeetaの記事通りにDockerfileを作る事に固執する必要は無いという事です。なぜならVMの様にコンテナの中から環境を自力で作る方が速いこともあるからです。今回の様にDocker Image に書き出して再利用することも可能です。