【Dockerネットワーク】コンテナ間の通信に挑戦する【RailsとMysql】

【Dockerネットワーク】コンテナ間の通信【RailsとMysql】

前回、Dockerfileを使ったDockerイメージの作り方を解説しました。

今回は、RailsとMysqlのDockerfileからコンテナを起動させ、「Dockerネットワーク」を使ったコンテナ間通信をしてみます。

  1. Dockerネットワークの作成
  2. Mysqlコンテナの作成と起動
  3. Railsコンテナの作成と起動
  4. ブラウザからRailsにアクセス

コンテナ間で通信する方法は、Dockerネットワークを使った方法以外にも、「--link」オプションをコンテナ起動時に指定する方法もあります。

ですが、このオプションは公式で非推奨とされているため、ここでは紹介しません。

キツネ

ただでさえ覚えることが多いんだから必要な知識に絞るよ!

Dockerネットワークの作成

Dockerネットワークとは、複数のDockerコンテナをまとめて管理するための仕組みです。

Dockerネットワークを利用することで、コンテナにつけた名前をホスト名として指定できるようになり、コンテナ間での通信が簡単に実現できます。

サクッと作成できるので、まずはDockerネットワークを作ってみましょう。

Dockerネットワークを作成
$ Dockerネットワーク作成
$ docker network create test-network

# Dockerネットワーク一覧
$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
0061ad21155a        bridge              bridge              local
52c761fea972        host                host                local
a3a448796918        none                null                local
9d32fabfc11d        test-network        bridge              local

キツネ

Dockerネットワークの設定はこれで終わりだよ!

Mysqlのイメージ作成からコンテナ起動まで

次に、Railsと接続するために使うMysqlのコンテナを起動させましょう。

ここでは、新しく「docker」ディレクトリを作成し、以下のような構成でファイルを準備したあと、Mysqlコンテナを起動させます。

Mysqlのディレクトリ構成
docker
└── mysql
    ├── Dockerfile
    └── app.cnf

MysqlのDockerfileを作成

まずは、Mysqlのイメージを作るためにDockerfileを作成します。

ここでは、「Mysql8.0」をベースイメージを使用しますが、1つだけ注意することがあります。

コメントにも書いてありますが、Mysql8.0のデフォルト認証方式のままだとエラーが発生するため、Mysql5.7以前の認証方式に変更します。

docker/mysql/Dockerfile
# Mysqlをインストール
FROM mysql:8.0

# Railsから接続する際に「Authentication plugin 'caching_sha2_password' cannot be loaded:」とエラーが発生するため
# Mysqlの認証方式を「caching_sha2_password」から「mysql_native_password」に変更
COPY app.cnf /etc/mysql/conf.d/app.cnf

「COPY」コマンドでホストマシンにある「app.cnf」ファイルをコンテナにコピーしています。

「app.cnf」ファイルは、僕が作ったMysqlの設定ファイルです。

docker/mysql/app.cnf
[mysqld]
default_authentication_plugin= mysql_native_password

Mysqlコンテナの作成と起動

Mysqlのイメージを作成し、コンテナの作成と起動をおこないます。

注目してほしいところは、「--network」オプションで、さきほど作ったDockerネットワークを指定しているところです。

これにより、指定されたネットワークの中でMysqlコンテナが起動します。

また、コンテナを作成する際に「-e」オプションでMysqlのパスワードを設定しています。

「-e」オプションは「environment(環境)」の略で、コンテナ内で利用する環境変数を設定できます。

Mysqlコンテナを作成
# 移動
cd /path/to/docker

# Dockerイメージ作成(ビルド)
$ docker build -t mysql ./mysql
Sending build context to Docker daemon  3.072kB
Step 1/2 : FROM mysql:8.0
8.0: Pulling from library/mysql
Digest: sha256:415ac63da0ae6725d5aefc9669a1c02f39a00c574fdbc478dfd08db1e97c8f1b
Status: Downloaded newer image for mysql:8.0
 ---> c7109f74d339
Step 2/2 : COPY app.cnf /etc/mysql/conf.d/app.cnf
 ---> bfb0496f17cf
   :
   :

# Mysqlコンテナの作成と起動
$ docker run --name mysql --network test-network -e MYSQL_ROOT_PASSWORD=root -d mysql
56368bf5241f6be8ebe85996cac852cbed2e2998a44bdcad237176a4de232333

# コンテナを確認
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                 NAMES
56368bf5241f        mysql               "docker-entrypoint.s…"   About a minute ago   Up About a minute   3306/tcp, 33060/tcp   mysql

Railsのイメージ作成からコンテナの起動まで

ここでは、Rubyのベースイメージを使ってRailsイメージを作成します。

Dcokerビルドに必要な以下のファイルを準備し、Dockerイメージを作成することで、最終的にRailsコンテナが起動します。

Railsのディレクトリ構成
docker
└── rails
    ├── Dockerfile
    ├── Gemfile
    ├── Gemfile.lock
    └── config
        └── database.yml

RailsのDockerfileを作成

まずは、基本となるDockerfileを作成します。

Rubyのベースイメージを使い、その上にRails環境を構築するためのコマンドを記述していきます。

何をしているかは、各命令コマンドのコメントを読んでもらえると理解できると思います。

docker/rails/Dockerfile
# Rubyをインストール
FROM ruby:2.6

# 必要なパッケージをインストール
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - \
    && apt-get install -y nodejs

# 公式では以下のコマンドを推奨しているが、nodeのバージョンが低くBootstrapが使えない
# RUN apt-get update -qq && apt-get install -y nodejs

# 環境変数を設定
ENV APP_HOME /app

# ディレクトリの作成と移動
WORKDIR $APP_HOME

# ホストのGemfileなどをコンテナへコピー
COPY Gemfile $APP_HOME/Gemfile
COPY Gemfile.lock $APP_HOME/Gemfile.lock

# BundlerでGemをインストール
RUN bundle install

# Railsアプリを作成(新規でアプリを作成する場合のみ)
RUN rails new . --database=mysql

# DBの設定ファイル書き換え(新規でアプリを作成する場合のみ)
COPY ./config $APP_HOME/config

# 3000番ポート解放
EXPOSE 3000

# コンテナ起動時にRailsサーバを起動
CMD ["rails", "server", "-b", "0.0.0.0"]

Dockerfileで必要となる「Gemfile」と「Gemfile.lock」を作成します。

「Gemfile.lock」は空ファイルを作成(ファイルだけ用意)し、「Gemfile」は新しくRailsをインストールするための記述をします。

docker/rails/Gemfile
$ source 'https://rubygems.org'
gem 'rails', '5.2.3'

次に、RailsからMysqlへのアクセスに必要な設定ファイルを作成します。

以下は、Railsで自動生成される「database.yml」をベースに、「password」や「host」を変更したものです。

同じDockerネットワークの中でRailsとMysqlのコンテナを起動させる予定なので、「database.yml」の中でもMysqlのコンテナ名(ホスト名)を指定できるようになります。

docker/rails/config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: root
  host: mysql

development:
  <<: *default
  database: app_development

test:
  <<: *default
  database: app_test

production:
  <<: *default
  database: app_production
  username: app
  password: <%= ENV['APP_DATABASE_PASSWORD'] %>

Railsコンテナの作成と起動

RailsのDockerfileが準備できたら、あとはビルドしてRailsコンテナを起動してみましょう。

Mysql同様、コンテナ起動時に「--network」オプションでDockerネットワークを指定しています。

Railsコンテナを作成
# 移動
cd /path/to/docker

# Railsイメージ作成(ビルド)
$ docker build -t rails ./rails
Sending build context to Docker daemon  5.632kB
Step 1/11 : FROM ruby:2.6
2.6: Pulling from library/ruby
Digest: sha256:90e8ee6a35bdecdb67cb1d5f0333c79604eab86b7a5a6ad2417378a216f7a316
Status: Downloaded newer image for ruby:2.6
 ---> 877a53569182
Step 2/11 : RUN curl -sL https://deb.nodesource.com/setup_10.x | bash -     && apt-get install -y nodejs
 ---> bb4c92a7781e
Step 3/11 : ENV APP_HOME /app
 ---> fe301413b470
Step 4/11 : WORKDIR $APP_HOME
 ---> Running in d9e435494245
Removing intermediate container d9e435494245
 ---> 6d74e94e6f71
Step 5/11 : COPY Gemfile $APP_HOME/Gemfile
 ---> 66c9af8d1539
Step 6/11 : COPY Gemfile.lock $APP_HOME/Gemfile.lock
 ---> 6db2c578f0eb
Step 7/11 : RUN bundle install
 ---> Running in 317163df5cea
   :
   :
Step 8/11 : RUN rails new . --database=mysql
 ---> Running in 852135468e53
   :
   :
Step 9/11 : COPY ./config $APP_HOME/config
 ---> 27b6c946f4cb
Step 10/11 : EXPOSE 3000
 ---> Running in f4299b8b396c
Removing intermediate container f4299b8b396c
 ---> 9b338a9b57f7
Step 11/11 : CMD ["rails", "server", "-b", "0.0.0.0"]
 ---> Running in f6b55d845e1b
   :
   :

# Railsコンテナの作成と起動
$ docker run --name rails --network test-network -p 3000:3000 -d rails
216f34ddf82f11f16c8829eba1e790cd3a482ed485eeaf94c70a9a4e674bda2e

# コンテナを確認
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
216f34ddf82f        rails               "rails server -b 0.0…"   59 seconds ago      Up 58 seconds       0.0.0.0:3000->3000/tcp   rails
56368bf5241f        mysql               "docker-entrypoint.s…"   13 minutes ago      Up 13 minutes       3306/tcp, 33060/tcp      mysql

ブラウザからアクセス

DockerでRailsの「unknown database」エラー

RailsとMysqlのコンテナが起動した状態で、「http://IPアドレス:3000」にアクセスすると、上のようなエラーが表示されると思います。

これは、MysqlコンテナにRails用のデータが存在しないために起こっています。

このエラーを解消するためには、Railsコンテナにログインし、データベースを作成するRailsコマンドを実行する必要があります。

Railsからデータベースを作成
# Railsコンテナにログイン
$ docker exec -it rails bash
root@216f34ddf82f:/app#

# Railsコマンドでデータベースを作成
$ rails db:create
Created database 'app_development'
Created database 'app_test'

Railsの初期画面

コマンドを実行すると、上のようなRailsの初期画面が表示されたはずです。

これで、Dockerネットワークを使った「Rails」と「Mysql」のコンテナ間通信ができました。

まとめ

ここでは、Dockerネットワークを学ぶために、RailsとMysqlのコンテナ間での通信をしてみました。

Dockerネットワークの仕組みはそこまで難しくありませんが、記事を書きながら「Dockerfileを作るの難しいな」と感じるところもありました。

Dockerfileを書くためには、Linuxなどのインフラ知識が必須となるので、ちょっと難しいなと感じた方はVagrantなどを使ってLinuxに慣れてから始めましょう。

次は「Docker Composeとは?Rails、Mysql、Nginxを構築して使い方を覚える」を読んで、より実用的なコンテナ間通信をおこないます。

テキストのコピーはできません。