👻
rails7.1で生成されるDockerfileを覗いてみる
はじめに
この記事を見て、「Dockerfile自動生成」で作られるDockerfileにとても興味がわいたので、備忘録としてのメモです
ディレクトリ構成
compose.yml
api(ディレクトリ)
├ Dockerfile
├ Gemfile
└ Gemfile.lock
準備
ファイル生成
touch compose.yml
mkdir api/
touch api/Dockerfile
touch api/Gemfile
touch api/Gemfile.lock
compose.yml
services:
api:
build:
context: ./api
container_name: api
ports:
- 3000:3000
environment:
RAILS_ENV: development
DB_HOST: mysql
DB_NAME: root
DB_PASSWORD: password
depends_on:
- mysql
volumes:
- ./api:/api
mysql:
image: public.ecr.aws/docker/library/mysql:8.1
container_name: mysql
volumes:
- mysql_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: password
TZ: "Asia/Tokyo"
volumes:
mysql_data:
Dockerfile
FROM public.ecr.aws/docker/library/ruby:3.2.2
RUN apt-get update -qq
RUN apt-get install -y build-essential nodejs
WORKDIR /api
COPY Gemfile Gemfile.lock /api/
RUN bundle install
Gemfile
source 'https://rubygems.org'
gem 'rails'
コマンド
docker compose build
rails new のオプションを確認
docker compose run --rm api rails new -h
dockerfile用のオプションが追加されてるのが分かります
表示内容
Usage:
rails new APP_PATH [options]
Options:
[--skip-namespace], [--no-skip-namespace] # Skip namespace (affects only isolated engines)
[--skip-collision-check], [--no-skip-collision-check] # Skip collision check
-r, [--ruby=PATH] # Path to the Ruby binary of your choice
# Default: /usr/local/bin/ruby
-n, [--name=NAME] # Name of the app
-m, [--template=TEMPLATE] # Path to some application template (can be a filesystem path or URL)
-d, [--database=DATABASE] # Preconfigure for selected database (options: mysql/trilogy/postgresql/sqlite3/oracle/sqlserver/jdbcmysql/jdbcsqlite3/jdbcpostgresql/jdbc)
# Default: sqlite3
-G, [--skip-git], [--no-skip-git] # Skip git init, .gitignore and .gitattributes
+ [--skip-docker], [--no-skip-docker] # Skip Dockerfile, .dockerignore and bin/docker-entrypoint
[--skip-keeps], [--no-skip-keeps] # Skip source control .keep files
-M, [--skip-action-mailer], [--no-skip-action-mailer] # Skip Action Mailer files
[--skip-action-mailbox], [--no-skip-action-mailbox] # Skip Action Mailbox gem
[--skip-action-text], [--no-skip-action-text] # Skip Action Text gem
-O, [--skip-active-record], [--no-skip-active-record] # Skip Active Record files
[--skip-active-job], [--no-skip-active-job] # Skip Active Job
[--skip-active-storage], [--no-skip-active-storage] # Skip Active Storage files
-C, [--skip-action-cable], [--no-skip-action-cable] # Skip Action Cable files
-A, [--skip-asset-pipeline], [--no-skip-asset-pipeline] # Indicates when to generate skip asset pipeline
-a, [--asset-pipeline=ASSET_PIPELINE] # Choose your asset pipeline [options: sprockets (default), propshaft]
# Default: sprockets
-J, --skip-js, [--skip-javascript], [--no-skip-javascript] # Skip JavaScript files
[--skip-hotwire], [--no-skip-hotwire] # Skip Hotwire integration
[--skip-jbuilder], [--no-skip-jbuilder] # Skip jbuilder gem
-T, [--skip-test], [--no-skip-test] # Skip test files
[--skip-system-test], [--no-skip-system-test] # Skip system test files
[--skip-bootsnap], [--no-skip-bootsnap] # Skip bootsnap gem
[--skip-dev-gems], [--no-skip-dev-gems] # Skip development gems (e.g., web-console)
[--dev], [--no-dev] # Set up the application with Gemfile pointing to your Rails checkout
[--edge], [--no-edge] # Set up the application with a Gemfile pointing to the 7-1-stable branch on the Rails repository
--master, [--main], [--no-main] # Set up the application with Gemfile pointing to Rails repository main branch
[--rc=RC] # Path to file containing extra configuration options for rails command
[--no-rc], [--no-no-rc] # Skip loading of extra configuration options from .railsrc file
[--api], [--no-api] # Preconfigure smaller stack for API only apps
[--minimal], [--no-minimal] # Preconfigure a minimal rails app
-j, --js, [--javascript=JAVASCRIPT] # Choose JavaScript approach [options: importmap (default), bun, webpack, esbuild, rollup]
# Default: importmap
-c, [--css=CSS] # Choose CSS processor [options: tailwind, bootstrap, bulma, postcss, sass] check https://github.com/rails/cssbundling-rails for more options
-B, [--skip-bundle], [--no-skip-bundle] # Don't run bundle install
[--skip-decrypted-diffs], [--no-skip-decrypted-diffs] # Don't configure git to show decrypted diffs of encrypted credentials
Runtime options:
-f, [--force] # Overwrite files that already exist
-p, [--pretend], [--no-pretend] # Run but do not make any changes
-q, [--quiet], [--no-quiet] # Suppress status output
-s, [--skip], [--no-skip] # Skip files that already exist
Rails options:
-h, [--help], [--no-help] # Show this help message and quit
-v, [--version], [--no-version] # Show Rails version number and quit
Description:
The `rails new` command creates a new Rails application with a default
directory structure and configuration at the path you specify.
You can specify extra command-line arguments to be used every time
`rails new` runs in the .railsrc configuration file in your home directory,
or in $XDG_CONFIG_HOME/rails/railsrc if XDG_CONFIG_HOME is set.
Note that the arguments specified in the .railsrc file don't affect the
default values shown above in this help message.
You can specify which version to use when creating a new rails application
using `rails _<version>_ new`.
Examples:
`rails new ~/Code/Ruby/weblog`
This generates a new Rails app in ~/Code/Ruby/weblog.
`rails _<version>_ new weblog`
This generates a new Rails app with the provided version in ./weblog.
`rails new weblog --api`
This generates a new Rails app in API mode in ./weblog.
`rails new weblog --skip-action-mailer`
This generates a new Rails app without Action Mailer in ./weblog.
Any part of Rails can be skipped during app generation.
プロジェクト構築
rails newのコマンド
docker compose run --rm api rails new . --force --database=mysql --api --minimal --skip-git
生成されたDockerfileを確認
api/Dockerfile
# syntax = docker/dockerfile:1
# Make sure RUBY_VERSION matches the Ruby version in .ruby-version and Gemfile
ARG RUBY_VERSION=3.2.2
FROM registry.docker.com/library/ruby:$RUBY_VERSION-slim as base
# Rails app lives here
WORKDIR /rails
# Set production environment
ENV RAILS_ENV="production" \
BUNDLE_DEPLOYMENT="1" \
BUNDLE_PATH="/usr/local/bundle" \
BUNDLE_WITHOUT="development"
# Throw-away build stage to reduce size of final image
FROM base as build
# Install packages needed to build gems
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y build-essential default-libmysqlclient-dev git pkg-config
# Install application gems
COPY Gemfile Gemfile.lock ./
RUN bundle install && \
rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git
# Copy application code
COPY . .
# Final stage for app image
FROM base
# Install packages needed for deployment
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y curl default-mysql-client && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives
# Copy built artifacts: gems, application
COPY --from=build /usr/local/bundle /usr/local/bundle
COPY --from=build /rails /rails
# Run and own only the runtime files as a non-root user for security
RUN useradd rails --create-home --shell /bin/bash && \
chown -R rails:rails db log tmp
USER rails:rails
# Entrypoint prepares the database.
ENTRYPOINT ["/rails/bin/docker-entrypoint"]
# Start the server by default, this can be overwritten at runtime
EXPOSE 3000
CMD ["./bin/rails", "server"]
とりあえず、そのまま利用してみる
api/config/database.yml
・・・省略・・・
adapter: mysql2
encoding: utf8mb4
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: <%= ENV.fetch("DB_NAME") { 'root' } %>
password: <%= ENV.fetch("DB_PASSWORD") { 'password' } %>
host: <%= ENV.fetch("DB_HOST") { 'localhost' } %>
・・・省略・・・
コマンド
docker compose build
docker compose run --rm api rake db:drop db:create db:migrate db:seed
docker compose up
問題なく稼働できました!
さいごに
まさかrails newでDockerfileまで作ってくれるとは思っていませんでした。
今回、Dockerfileの自動生成に期待して、Dockerfileを質素な作りで実施しましたが、予想以上にしっかりしたものが作られたので感激です。
オワコンとも言われてますが、常に進化し続けるのもrailsの強みでもあると思っています。
今後にも期待です。
Discussion