質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.45%

  • Ruby on Rails

    9103questions

    Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

  • docker-compose

    261questions

RailsとNginxのUNIX DOMAIN SOCKETについて

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 3
  • VIEW 92

ishiatama

score 1

実現したいこと

ホスト上のRailsとコンテナ上のNginxをUNIX DOMAIN SOCKETで連携させたい

現状

Docker(docker-compose)でRailsコンテナとNginxコンテナを作成し、コンテナ間のsocket通信することは出来たのですが
Railsをコンテナではなく、ホスト(Mac)側に環境を作った際に、Nginxでconnect() to unix:///var/www/myapp/tmp/sockets/puma.sock failed (111: Connection refused) while connecting to upstream, client: 172.19.0.1, server: localhost, request: "GET / HTTP/1.1", upstream: "http://unix:///var/www/myapp/tmp/sockets/puma.sock:/", host: "localhost"のエラーが発生し通信できません。
そもそもホストとコンテナ間でsocket通信は可能なのでしょうか?


追記

  • localhost:3000で通信できましたが、localhostだと上記のエラーになります。
  • Macにbrewでnginxをインストールし、同じconf設定にするとlocalhostでWebページが表示されることを確認しました。

Nginxの設定は以下のとおりです。

# docker-compose.yml
version: '2'
services:
  postgres:
    image: postgres
    ports:
      - 5432:5432
    environment:
      POSTGRES_USER: devuser
      POSTGRES_PASSWORD: password
      POSTGRES_DB: dev
    volumes:
      - ./containers/postgresql/init.sh:/docker-entrypoint-initdb.d/init.sh
      - ./data/pg-data:/var/lib/postgresql/data
  nginx:
    build: ./containers/nginx
    ports:
      - 80:80
    volumes:
      - ./public:/var/www/myapp/public
      - ./tmp:/var/www/myapp/tmp
      - ./log:/var/www/myapp/log
    environment:
      TZ: Asia/Tokyo
    depends_on:
      - postgres
FROM nginx

RUN apt-get update -qq && apt-get -y install apache2-utils
ENV RAILS_ROOT /var/www/myapp
WORKDIR $RAILS_ROOT

ADD default.conf /tmp/default.nginx
ADD nginx.conf /tmp/nginx.nginx

RUN envsubst '$RAILS_ROOT' < /tmp/default.nginx > /etc/nginx/conf.d/default.conf
RUN envsubst '$RAILS_ROOT' < /tmp/nginx.nginx > /etc/nginx/nginx.conf

EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
# nginx.conf

user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile    on;
    tcp_nopush  on;

    keepalive_timeout  75;

    gzip  on;

    include /etc/nginx/conf.d/*.conf;
}
# /etc/nginx/conf.d/default.conf

upstream puma {
    server unix://$RAILS_ROOT/tmp/sockets/puma.sock;
}

server {
    listen       80;
    server_name  localhost;

    root $RAILS_ROOT/public;
    index  index.html;

    access_log $RAILS_ROOT/log/nginx.access.log;
    error_log $RAILS_ROOT/log/nginx.error.log;

    # deny requests for files that should never be accessed
    location ~ /\. {
        deny all;
    }

    location ~* ^.+\.(rb|log)$ {
        deny all;
    }

    # serve static (compiled) assets directly if they exist (for rails production)
    location ~ ^/(assets|images|javascripts|stylesheets|swfs|system)/ {
        try_files $uri @rails;

        access_log off;
        gzip_static on; # to serve pre-gzipped version

        expires max;
        add_header Cache-Control public;

        # Some browsers still send conditional-GET requests if there's a
        # Last-Modified header or an ETag header even if they haven't
        # reached the expiry date sent in the Expires header.
        add_header Last-Modified "";
        add_header ETag "";
        break;
    }

    location / {
        try_files $uri @rails;
    }

    location @rails {
        proxy_pass        http://puma;
        proxy_set_header  Host $http_host;
        proxy_set_header  X-Real-IP $remote_addr;
        proxy_set_header  Client-IP $remote_addr;
        proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header  X-Forwarded-Proto $scheme;
    }

    error_page  404              /404.html;
    error_page  500 502 503 504  /500.html;
    location = /500.html {
        root   $RAILS_ROOT/public;
    }
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

ホスト側で起動したアプリケーションのソケットのあるディレクトリを、コンテナ側にVolumeでマウントさせる、というのはどうでしょうか?

20190612 追記
ホスト側のdocker.sockをコンテナ側にマウントさせてDockerのAPIを叩く...というのは試したりするので、気になってrailsをソケットであげて、コンテナ側にソケットファイルをマウントさせて、コンテナ内部からsocatでリクエストを出す、ということをやってみました。

Docker for Macに限ってですが、この場合、コンテナ側からは socat[16] E connect(5, AF=1 "/tmp/sockets/puma.sock", 24): Connection refused のメッセージが出たので、エラーメッセージとしては同様かと思います。
もし環境が違っていても再現するようでしたら、とりあえずはホスト側のアプリケーションもTCPで上げておくのが良いのかな...とは思っています。なにか参考になれば幸いです。

関連:
https://forums.docker.com/t/cant-connect-to-host-listening-unix-socket-from-container-vm/15526/2

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/06/11 18:29

    ご回答ありがとうございます。マウントはdocker-compose.ymlで設定しております。こちら掲載しておらず申し訳ございません。

    キャンセル

  • 2019/06/11 20:39

    失礼しました。docker-compose.yml も上記に添えていただくのは可能でしょうか?

    キャンセル

  • 2019/06/11 23:08 編集

    docker-compose.ymlを記載しました。また、こちらで試したことについては追記として記述しています。ご確認お願いいたします。

    キャンセル

  • 2019/06/12 10:46

    こんにちは、追記ありがとうございます!
    もしかして実施している環境はMacOSでしょうか?(Docker hostがMacOS / Docker for Mac)

    わたしも実験してみたのですが、Docker for MacだとVolume optionを使ってソケットファイルをマウントさせても、うまく通信できないようです。回答の方に追記しておきますね。
    Unix(たとえばホストがUbuntu)だとできるのかな?(個人的な興味で確認するかもしれません)

    キャンセル

  • 2019/06/12 18:31 編集

    実行環境は仰るとおりMacです。私の方でも色々と試してみましたが上手くできないようです。ネットワークの知識があまりなく、どういう仕組みで出来ないのかはわかりませんが・・・。
    Dockerのドキュメントを確認すると`host.docker.internal`で通信できると書いていたので、これをNginxのupstreamに設定したところ正常に動作することを確認できました。
    https://docs.docker.com/docker-for-mac/networking/

    一旦はこれで完了と致しますが、ご確認したことを更に追記された際にはぜひ参考にさせていただきます。ご対応誠にありがとうございました。

    キャンセル

  • 2019/06/12 19:17

    こちらこそ、ちょうど色々な組み合わせで試すことがあったので、制約などが分かって良い経験でした。
    host.docker.internalは、Docker for Macの場合利用できる指定方法で、コンテナ内からDocker for Mac (ホストになっているMac側)を参照したい場合、IPでなく名前で指定できるものだったかと思います。
    結果的には、ホスト(Mac側)のアプリケーションはTCPで上げた形でしょうか?

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.45%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Ruby on Rails

    9103questions

    Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

  • docker-compose

    261questions