概要
Dockerfile ともっと仲良くしたい。
すごく大きな不満があるわけじゃないけれど、↓のようなことができると嬉しい。
- 1 つのプロジェクト内で複数の Dockerfile を用途に応じて使い分けたい
- ある Dockerfile から別の Dockerfile を include したい
- Dockerfile 内で変数が使えたりすると嬉しい
Rails プロジェクトを想定していますが、他のフレームワークでも rake と ActionView が使えるならイケるはず。
実装
rake dockerfile:build
という rake タスクを作ってみる。
lib/tasks/dockerfile.rake
namespace :dockerfile do
desc "build Dockerfile"
task :build => :environment do
view_context = ActionView::Base.new('.')
# 必要に応じて値をバインドする
view_context.assign(name: 'hoge')
out = view_context.render(template: "Dockerfile.#{Rails.env}", prefixes: '')
File.write("#{Rails.root}/Dockerfile", out)
end
end
プロジェクトのルートにそれぞれの環境に応じた Dockerfile を erb 形式で作ってあげる。
ProjectRootDir
├── Dockerfile.base.erb
├── Dockerfile.development.erb
├── Dockerfile.production.erb
├── Dockerfile.staging.erb
└── Dockerfile.test.erb
中身はこんな感じ。
Dockerfile.base.erb
# Add application
WORKDIR /tmp
ADD Gemfile Gemfile
ADD Gemfile.lock Gemfile.lock
RUN bundle install
RUN mkdir /home/app/my_app
ADD . /home/app/my_app
RUN chown -R app:app /home/app/my_app
WORKDIR /home/app/my_app
RUN bundle install
Dockerfile.development.erb
FROM kakipo/my-base:latest
MAINTAINER <%= @name %>
<%= render file: 'Dockerfile.base.erb' %>
# Add mysql
# only for development
RUN sudo apt-get -y install mysql-server
RUN mkdir /etc/service/mysql
ADD docker/mysql.sh /etc/service/mysql/run
EXPOSE 80
# Use baseimage-docker's init system.
CMD ["/sbin/my_init"]
で、 rake dockerfile:build RAILS_ENV=development
としてやると、プロジェクトのルートディレクトリに Dockerfile
が作成される。
Dockerfile
FROM kakipo/my-base:latest
MAINTAINER hoge
# Add application
WORKDIR /tmp
ADD Gemfile Gemfile
ADD Gemfile.lock Gemfile.lock
RUN bundle install
RUN mkdir /home/app/my_app
ADD . /home/app/my_app
RUN chown -R app:app /home/app/my_app
WORKDIR /home/app/my_app
RUN bundle install
# Add mysql
# only for development
RUN sudo apt-get -y install mysql-server
RUN mkdir /etc/service/mysql
ADD docker/mysql.sh /etc/service/mysql/run
EXPOSE 80
# Use baseimage-docker's init system.
CMD ["/sbin/my_init"]
上手に焼けました。
終わりに
やんごとなき事情によってこんな対応になってしまったのだけれども、もっといい方法があると思う。