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

【Docker】Rails+MySQLの環境をDockerで構築中「ポートの衝突」に遭遇してから解決するまで

はじめに

DockerでRuby on Rails + MySQLの環境を構築中にいわゆる「ポートの衝突」に遭遇したので解決までを記載します。

同じような箇所でハマった方の参考になればと思います。

この記事が役に立つ方

  • DockerでRails+MySQLの開発環境を行いたいと考えている
  • Docker初心者

この記事のメリット

  • ポートの衝突を回避する方法が分かる

環境

  • macOS Mojave バージョン10.14.6
  • シェル:zsh
  • Ruby:2.6.5
  • Rails:5.2.2
  • MySQL:5.7
  • Docker:19.03.5

Dockerfile

こちらを参考に、rubyのバージョンのみ、現行安定版である2.6.5にしています。
丁寧すぎるDocker-composeによるrails5 + MySQL on Dockerの環境構築(Docker for Mac) - Qiita

Dockerfile
FROM ruby:2.6.5

RUN apt-get update -qq && \
    apt-get install -y build-essential \
                       libpq-dev \
                       nodejs

RUN mkdir /app_name
ENV APP_ROOT /app_name
WORKDIR $APP_ROOT

ADD ./Gemfile $APP_ROOT/Gemfile
ADD ./Gemfile.lock $APP_ROOT/Gemfile.lock

RUN bundle install
ADD . $APP_ROOT

docker-compose.yml

docker-compose.yml
version: '3'
services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: root
    ports:
      - "3306:3306"

  web:
    build: .
    command: rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/app_name
    ports:
      - "3000:3000"
    links:
      - db
    tty: true

エラー内容

$ docker-compose run web rails new . --force --database=mysql --skip-bundle

上記コマンドでrails newしたかったのですが、以下エラーが発生してしまいました。

Error starting userland proxy: listen tcp 0.0.0.0:3306: bind: address already in use

address already in use
とあるので、既にポートが使われているらしい。

ここから解決していきます。

1.ポート番号の変更(これだけでは解決せず)

過去、DockerでMySQLを使用したときもポートは3306を使用したことはあったなと思ったので、ホスト側のポートをずらしてみて検証します。

docker-compose.yml
services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: root
    ports:
      - "3316:3306" # ここを修正。左側はホスト、右側はコンテナを表す。
      # コンテナ間の通信は3306が使われるようなので、右側はそのまま。

しかし、同様のエラーが発生。

Error starting userland proxy: listen tcp 0.0.0.0:3306: bind: address already in use

ポートを変えたのに、なぜ?

※今思えば、ここでホスト側で同じポートが使われていないかを以下コマンドで調べることがベストだったかもしれません。無駄撃ちが減ったはず。

$ sudo lsof -i -P | grep "LISTEN"

次の策に移ります。

2.docker-compose down (これで無事解決)

以下記事をstack overflowで見つけました。(phpですがエラーは同じ)
php - Error starting userland proxy: listen tcp0.0.0.0:3306: bind: address already in use - Stack Overflow

Probably you have already a MySQL service running in port 3306. You should close it first.
Then try to end docker-compose down

すでにMySQLがポート3306で起動している可能性があるので、とりあえずdocker-compose downしてからもう一度コマンドを実行してみろとのこと。

エラー出てたのに起動してるの?と疑問を抱きつつも、やってみます。

$ docker-compose down

$ docker-compose run web rails new . --force --database=mysql --skip-bundle

無事rails new出来ました!

一回目のコマンドでエラーが出ながらも起動してしまっていたのか?
スッキリしませんが一応解決です。

おわりに

これまであまりポートを意識することがなかったため、いい勉強になりました:writing_hand:

docker-compose.ymlについてもまだ理解不十分なため、次は以下記事を見て勉強しようと思います。
Docker Compose - docker-compose.yml リファレンス - Qiita

参考にさせて頂いたサイト(いつもありがとうございます)

mysql-Dockerを使用するときに「ポートの衝突」を回避する方法 - コードログ
mysql - How do I avoid ‘port collision’ when using docker? - Stack Overflow
Docker Compose - docker-compose.yml リファレンス - Qiita

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
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