Help us understand the problem. What is going on with this article?

docker-composeとネットワーク、コンテナのホスト名の割り当てなどを理解する

More than 1 year has passed since last update.

Railsなどサーバーサイド開発でDockerを使っているなら、docker-composeを使っている人は多いだろう。docker-compose.ymlでRails環境とDB環境(これらをサービスと読ぶ)を定義し、docker-compose upで、2つのコンテナを起動するのはよくあることだ。

よくあるケースなのでググればすぐ出てくるし、Dockerのネットワーク構成についてあまり理解してなくても問題なかったりする。しかし、Railsから別コンテナのSFTPサーバーにファイルをアップロードしたいとかになると、ググってもあまり出てこず、Dockerのネットワークについて理解しておかないとハマるかもしれない。

docker-compose.ymlで宣言したサービスは、docker-compose upなどでコンテナ起動すると、同一のネットワークに所属することになる(Dockerネットワークと呼ぶ)。そして、それぞれホスト名が割り当てられる。そのホスト名はサービス名、もしくはdocker-compose.ymlで指定したコンテナ名となる。

このようなdocker-compose.ymlを定義があるとする。実際に動作検証はしていない。あくまで例。

docker-compose.yml
version: '2'
services:
  db:
    image: mysql:5.6
    container_name: my_db
    environment:
      MYSQL_ROOT_PASSWORD: password
    ports:
      - '3316:3306'

  sftp:
    image: atmoz/sftp
    container_name: my_sftp
    volumes:
      - ./tmp/upload:/home/foo/upload
    ports:
      - '2222:22'
    command: foo:pass:1001

  rails:
    build:
      context: .
      dockerfile: Dockerfile-rails
    command: bundle exec rails server -p 3000 -b '0.0.0.0'
    container_name: my_rails
    environment:
      RAILS_ENV: development
    ports:
      - '3000:3000'
    links:
      - db
      - sftp

docker-compose upなどで3つのコンテナが起動される。

サービス名 コンテナ名
db my_db
sftp my_sftp
rails my_rails

このコンテナ名およびサービス名がホスト名となる。

Railsのconfig/database.ymlには以下のように書いていることだろう。これは同一ネットワーク内でdbというホスト名でアクセスできるからだ。

default: default
〜〜〜
  host: db
  port: 3306
〜〜〜

注目すべきはポート番号。ここでは3306を指定している。docker-composeのportsで'3316:3306'のように定義してあるが、前者の3316はホストマシンからアクセスする際のポートである。Dockerコンテナが所属するネットワーク内では3316ではアクセスできない。つまりRaisは後者の3306でDBへアクセスする。

あなたが実際に使っているホストマシンで、MySQLやSFTPのデフォルトのポートは使いたくないだろう。競合の可能性があるからだ。だから、portsの前者で指定するポートは、他と重複しないものを指定し、後者はDockerネットワーク内なのでデフォルトのポートを指定しても問題ないということになる。

Railsでsftpコンテナへアクセスする際には、以下のようにすればいい。

hostname = "sftp" # my_sftpでも良い
username = "foo"
option = {
  password: "pass"
  port: 22
}
Net::SFTP.start(hostname, username, option) do |sftp|
〜〜〜何らかの処理〜〜〜
end

ここでポートに22を指定しているのも先程と同様の理由である。sftpサービスはportsを2222:22で定義している。つまりホストマシンからは2222でログインでき、Dockerネットワーク内では22でログインできる。

Dockerネットワークを詳しく見る

以下のコマンドを打つと、Dockerネットワークの一覧を見ることが出来る。

$ docker network list

その中に、"{docker-compose.ymlが配置されているフォルダ名}+_default"という名前のネットワークがあるはずだ。(この名前はフォルダ名のハイフンやドットは省略されているかもしれない)

例えばそれがmyapp_defaultだったとしよう。次に以下のように打つ。

$ docker network inspect myapp_default

ずらずらと出力がなされるが、Containersの項目に割り当てらたIPアドレスなどを確認できるはずだ。

        "Containers": {
            "4238*******************************0": {
                "Name": "myapp_sftp",
                "EndpointID": "c11*******************************40",
                "MacAddress": "02:**:**:**:00:02",
                "IPv4Address": "172.22.0.2/16",
                "IPv6Address": ""
            },
            "75*******************************06": {
                "Name": "myapp_db",
                "EndpointID": "cf*******************************be",
                "MacAddress": "02:**:**:**:00:03",
                "IPv4Address": "172.22.0.3/16",
                "IPv6Address": ""
            },
            "dc*******************************2e": {
                "Name": "myapp_rails",
                "EndpointID": "41*******************************6e",
                "MacAddress": "02:**:**:**:00:04",
                "IPv4Address": "172.22.0.4/16",
                "IPv6Address": ""
            }
        },

もちろんこのIPアドレスは動的に割り当てられるのでプログラムから指定してはならない。固定であるホスト名で指定するべきである。

このようにDockerネットワークについて理解しておくと、コンテナからコンテナへ接続できないなどでハマった時に原因を特定できるかもしれない。

roba4coding
プログラマ&ディベロッパー&ハッカー。エンジニアではありません。主にアプリの開発をやってます。勉強会には一切顔を出さず、たいていウェブで済ませて独学。家に技術本らしきものは一冊もありません。炎上案件に召喚され黒魔法で消火活動を行う暗黒プログラマです。記事の内容による損害について当方は一切責任を負いませんのでご了承ください。
https://note.mu/roba4coding
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした