目的
できる限り最新の環境を、最低限で構築したい。
前提条件
開発環境
- macOS Catalina(ver. 10.15.7)
- Docker Desktop(ver. 3.03)
- Docker(ver. 20.10.0)
お断り
- あくまでも試験的に構築した環境です。
- 諸事情により、1つのコンテナに複数の役割を持たせています。
- 実際の実行時に「#」である場合であっても、「$」で表記しています。
- パスワードを直書きしていますが、これは試験的な環境であるためです。
実施
ベースになるイメージの作成
ディレクトリの作成
$ mkdir -p containers/base_image
$ cd containers/base_image
Dockerfileの記述
Dockerfileを記述する。
$ vi Dockerfile
Docker Hubの記述を参考に、systemdを使用可能にする。
CentOS Streamの公式情報を参考に、CentOS8からCentOS Streamに移行。
[Dockerfile]
FROM centos:latest
MAINTAINER tora_tz
ENV CONTAINER_NAME local/cos-stream
ENV CONTAINER_VERSION 20210104_01
# Centos Stream に移行
# CentOS Streamのリポジトリ情報をインストール
RUN dnf install -y centos-release-stream
# リポジトリ情報を削除
RUN dnf swap -y centos-{linux,stream}-repos
# 最新のパッケージに同期
RUN dnf distro-sync -y
イメージのビルドを実行
# ビルド
$ docker build --rm -t local/cos-stream .
# ビルドされたことを確認
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
local/cos-stream latest f0ccd16bd6fc 16 seconds ago 526MB
開発のベースとなるイメージを作成
Rubyが入っている、最低限開発に必要なイメージを作成します。
Dockerfileの作成
まずは最低限の内容での確認
$ mkdir ../dev_base
$ cd ../dev_base
$ vi Dockerfile
[Dockerfile]
FROM local/cos-stream
MAINTAINER tora_tz
# system update
RUN dnf -y upgrade; dnf clean all;
イメージのビルドを実行
$ docker build --rm -t local/dev_base:0.1 .
(中略)
Successfully tagged local/dev_base:0.1
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
local/dev_base 0.1 cab625bee967 10 seconds ago 532MB
local/cos-stream latest f0ccd16bd6fc 10 minutes ago 526MB
コンテナを作成
# 作成、起動する。
$ docker run -dit --name dev_base_container local/dev_base:0.1
# 作成されたコンテナを確認する。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ae0b8ebe78b2 local/dev_base:0.1 "/bin/bash" 5 seconds ago Up 5 seconds dev_base_container
※以降、起動するときは以下のようにします。
$ docker start dev_base_container
デフォルトで入っているものの確認
# コンテナの中に入る
$ docker exec -it dev_base_container bash
# CentOS Streamに移行できていることを確認。
$ cat /etc/centos-release
CentOS Stream release 8
# 入っているものを確認
$ dnf list installed
削除するときは
$ docker stop dev_base_container
$ docker rm dev_base_container
Dockerfileを以下のように書き直しました。
具体的には、以下の点を修正しました。
- Rubyのバージョン管理を行うための
rbenv
をインストール。 - Node.jsのバージョン管理を行うための
nodenv
をインストール。 - コンテナがどのバージョンか、内部から確認可能なように、環境変数の追加。
FROM local/cos-stream
MAINTAINER tora_tz
ENV CONTAINER_VERSION 0.2
# system update&install
RUN dnf -y upgrade && dnf install -y git && dnf clean all
# anyenv install
SHELL ["/bin/bash", "-c"]
RUN git clone https://github.com/anyenv/anyenv ~/.anyenv
ENV PATH ~/.anyenv/bin:$PATH
RUN echo 'eval "$(anyenv init -)"' >> ~/.bash_profile
RUN anyenv install --force-init
RUN anyenv install rbenv
RUN anyenv install nodenv
RUN exec $SHELL -l
rbenv、nodenvのパスが通っているか確認
# ビルド
$ docker run -dit --name dev_base_container local/dev_base:0.2
# --loginをつけないと、.bash_profileが動かない。
$ docker exec -it dev_base_container /bin/bash --login
$ rbenv install --list
2.5.8
2.6.6
2.7.2
3.0.0
$ nodenv install --list
(中略)
15.2.1
15.3.0
15.4.0
15.5.0
Ruby 3.0が入っていることを確認。
ビルド時の依存ライブラリを参考にDockerfileを修正。
[Dockerfile]
FROM local/cos-stream
MAINTAINER tora_tz
ENV CONTAINER_NAME dev_name
ENV CONTAINER_VERSION 0.3
# change bash
SHELL ["/bin/bash", "-c"]
# system update&install
RUN dnf upgrade -y \
&& dnf install -y dnf-plugins-core \
&& dnf config-manager --enable powertools \
&& dnf install -y sudo which git gcc make bzip2 openssl-devel libyaml-devel libffi-devel readline-devel zlib-devel gdbm-devel ncurses-devel \
&& dnf clean all
ENV DOCKER_USER developer
RUN useradd -mU ${DOCKER_USER}
# sudo設定追加
RUN echo '${DOCKER_USER} ALL=(ALL:ALL) ALL' | EDITOR='tee -a' visudo
# RUN echo '${DOCKER_USER} ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
# sudo権限を付与
RUN gpasswd -a ${DOCKER_USER} ${DOCKER_USER}
# sudo可能なグループに所属させる。
RUN usermod -aG wheel ${DOCKER_USER}
# パスワードを設定
RUN echo "${DOCKER_USER}:dev_pass" | chpasswd
# 実行ユーザを変更
USER ${DOCKER_USER}
ENV WORKSPACE_PATH /home/${DOCKER_USER}/workspace
RUN mkdir -p ${WORKSPACE_PATH}
WORKDIR ${WORKSPACE_PATH}
# anyenv install
RUN git clone https://github.com/anyenv/anyenv ~/.anyenv
ENV PATH ~/.anyenv/bin:$PATH
RUN echo 'eval "$(anyenv init -)"' >> ~/.bashrc
RUN anyenv install --force-init
RUN anyenv install rbenv
RUN anyenv install nodenv
RUN exec $SHELL -l
# Ruby&Node.js Install
RUN source ~/.bashrc \
&& rbenv install 3.0.0 \
&& rbenv global 3.0.0 \
&& nodenv install 15.5.0 \
&& nodenv global 15.5.0
イメージの作成・コンテナの起動
$ docker build --rm -t local/dev_base:0.3 .
$ docker stop dev_base_container
$ docker rm dev_base_container
$ docker run -dit --name dev_base_container local/dev_base:0.3
$ docker exec -it dev_base_container /bin/bash --login
$ ruby -v
ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-linux]
$ node -v
v15.5.0
$ gem -v
3.2.3
$ bundler -v
Bundler version 2.2.4
Rails開発のベースとなるイメージの作成
Dockerfileの作成
$ mkdir ../dev_rails_base
$ cd ../dev_rails_base
$ vi Dockerfile
[Dockerfile]
FROM local/dev_base:0.3
MAINTAINER tora_tz
ENV CONTAINER_NAME dev_rails_base
ENV CONTAINER_VERSION 0.1
USER ${DOCKER_USER}
ENV APP_ROOT ${WORKSPACE_PATH}/rails_test
RUN mkdir -p ${WORKSPACE_PATH}/rails_test
WORKDIR ${APP_ROOT}
USER root
# yarnのリポジトリを追加して、Railsの依存ライブラリをインストールする。
# see https://classic.yarnpkg.com/ja/docs/install/#centos-stable
RUN curl --silent --location https://dl.yarnpkg.com/rpm/yarn.repo | tee /etc/yum.repos.d/yarn.repo && dnf install -y yarn sqlite gcc-c++
# MariaDBパッケージリポジトリセットアップスクリプトを使い、リポジトリをセットアップする。
# see https://mariadb.com/kb/en/yum/
RUN curl -sS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | bash
# MariaDBをインストールする
RUN dnf upgrade -y && dnf install -y MariaDB-server galera-4 MariaDB-client MariaDB-shared MariaDB-backup MariaDB-common MariaDB-devel && dnf clean all
USER ${DOCKER_USER}
# Gemfileを追加する。
COPY --chown=${DOCKER_USER}:${DOCKER_USER} Gemfile ${APP_ROOT}
# Gemファイルを生成する。
RUN source ~/.bashrc \
&& bundle config set path 'vendor/bundle' \
&& bundle install \
&& bundle exec rails new . --force -d mysql --minimal
COPY --chown=${DOCKER_USER}:${DOCKER_USER} database.yml ${APP_ROOT}/config/database.yml
EXPOSE 3000
Gemファイル修正
$ vi Gemfile
[Gemfile]
# frozen_string_literal: true
source "https://rubygems.org"
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
gem "rails", '>= 6.1'
DB接続設定ファイルの修正
$ vi database.yml
[database.yml]
# MySQL. Versions 5.5.8 and up are supported.
#
# Install the MySQL driver
# gem install mysql2
#
# Ensure the MySQL gem is defined in your Gemfile
# gem 'mysql2'
#
# And be sure to use new-style password hashing:
# https://dev.mysql.com/doc/refman/5.7/en/password-hashing.html
#
default: &default
adapter: mysql2
encoding: utf8mb4
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: rails_user
password: test_password
host: localhost
development:
<<: *default
database: rails_test_development
port: 3315
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
<<: *default
database: rails_test_test
# As with config/credentials.yml, you never want to store sensitive information,
# like your database password, in your source code. If your source code is
# ever seen by anyone, they now have access to your database.
#
# Instead, provide the password or a full connection URL as an environment
# variable when you boot the app. For example:
#
# DATABASE_URL="mysql2://myuser:mypass@localhost/somedatabase"
#
# If the connection URL is provided in the special DATABASE_URL environment
# variable, Rails will automatically merge its configuration values on top of
# the values provided in this file. Alternatively, you can specify a connection
# URL environment variable explicitly:
#
# production:
# url: <%= ENV['MY_APP_DATABASE_URL'] %>
#
# Read https://guides.rubyonrails.org/configuring.html#configuring-a-database
# for a full overview on how database connection configuration can be specified.
#
production:
<<: *default
database: rails_test_production
username: rails_test
password: <%= ENV['RAILS_TEST_DATABASE_PASSWORD'] %>
イメージの作成・コンテナの起動
$ docker build --rm -t local/dev_rails_base:0.1 .
$ docker run -dit --name dev_rails_base_container -p49152:3000 local/dev_rails_base:0.1
$ docker exec -it dev_rails_base_container /bin/bash --login
# MariaDBの起動
$ echo dev_pass | sudo -S nohup mysqld_safe &
別タブで以下を実行する。
# MariaDB初期セットアップ
$ docker exec -it dev_rails_base_container /bin/bash --login
$ sudo mysql_secure_installation
Enter current password for root (enter for none):test_password
Switch to unix_socket authentication [Y/n]:n
Change the root password? [Y/n]:n
Remove anonymous users? [Y/n]:Y
Disallow root login remotely? [Y/n]:Y
Remove test database and access to it? [Y/n]:Y
Reload privilege tables now? [Y/n]:Y
Thanks for using MariaDB!
$ sudo mysql -u root -p
MariaDB [(none)]> use mysql;
MariaDB [mysql]> SELECT user, host, plugin FROM user;
+-------------+-----------+-----------------------+
| User | Host | plugin |
+-------------+-----------+-----------------------+
| mariadb.sys | localhost | mysql_native_password |
| root | localhost | mysql_native_password |
| mysql | localhost | mysql_native_password |
+-------------+-----------+-----------------------+
# Railsからアクセスするためのユーザを作成する。
MariaDB [mysql]> CREATE USER 'rails_user'@'%' identified by 'test_password';
MariaDB [mysql]> GRANT ALL PRIVILEGES ON *.* TO 'rails_user'@'%' WITH GRANT OPTION;
MariaDB [mysql]> SELECT user, host, plugin FROM user;
+-------------+-----------+-----------------------+
| User | Host | plugin |
+-------------+-----------+-----------------------+
|(中略) | | |
| rails_user | % | mysql_native_password |
+-------------+-----------+-----------------------+
MariaDB [mysql]> flush privileges;
MariaDB [mysql]> quit;
$ bin/rails db:create
Created database 'rails_test_development'
Created database 'rails_test_test'
# Railsを起動する。
$ bin/rails s -b 0.0.0.0
コンテナで起動したRails環境へのアクセス
今後の課題
- systemdを使えるようにする。(特権を持たせないとダメなようなので、場合によっては断念)
※一応試しましたが、ビルド時に
[OK]Started Update UTMP about System Runlevel Changes.
で止まるので、実施する場合はこの辺りの調査が必要。
- Docker Composeに乗り換え、コンテナを分割する。
- Visual Studio Codeから開発できるようにする。
- 手動でセットアップしているところも自動化する。
- MariaDBの自動起動設定を有効にする。(systemctlが使用できないので、mysqld_safeを使って……ですが、起動する時間を考慮する必要があるとのことなので、要対策)
- Sequel AceなどのクライアントからDBにアクセスできるようにする。
(ポート設定を追加して実施してみたができなかったので、要調査) - GitHubとの連携(アカウントは引数で渡す)
- ベタ書きしているパスワードなどの情報を、外から引数で渡せるようにする。
- ログインシェルを指定しなくて済むようにする。(ENTRYPOINTを使うなど……)