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

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

ただいまの
回答率

89.20%

Docker-compose内のapiサーバーへのリクエストがConnection refused

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 3,792

alberorana

score 46

私はdocker-composeでcodeigniter(localhost)とlaravel(api.localhost)の環境を構築しています。
codeigniter(localhost)からlaravel(api.localhost)へのapiリクエストをテストしていますが、NULLになってしまいます。

同じdocker-compose内だとIPアドレスが被ってしまうことが原因みたいなのですが、そこを解決する方法がわからないです。
その方法を教えていただければ幸いです。

 試した事

codeigniterコンテナから以下を試してみましたが

*curl http://laravel(コンテナ名)/api/test


ダメでした。

*curl http://google.com


だと取得できます。

Docker構成

codeigniter

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, DELETE, OPTIONS");
header("Access-Control-Allow-Headers: *");

$opt = array("http" => array('ignore_errors' => true));
//FALSE
$result = file_get_contents('http://api.localhost/api/test/', false, stream_context_create($opt));
//TRUE
$result = file_get_contents('https://yahoo.com', false, stream_context_create($opt));
var_dump($result);

・laravel(api.localhost)route api.php

Route::resource('test/', 'TestController');

TestController

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class TestController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
       return response()->json(['apple' => 'red', 'peach' => 'pink']);
    }
}

docker-compose.yml

version: '2'
services:
  #MySQLのデータが保存されるので、消さない!
  data:
    image: busybox
    volumes:
      - ./misc/data:/var/lib/mysql
  nginx:
    image: nginx:1.10
    ports:
    #ポート番号は変更OK→ただし、nginxフォルダのdefault.confの設定も変更すること!
      - "80:80"
    #volumesがローカルからコンテナにマウントされるディレクトリ
    volumes:
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
        #各自切り替える事
      - /Users/alberorana/:/var/www/html/
      - /Users/alberorana/api:/var/www/html/api
    links:
      - code
      - laravel
    container_name: nginx

  code:
    build: ./codeigniter
    volumes:
      - /Users/alberorana/:/var/www/html/
      - ./php/php.ini:/usr/local/etc/php/conf.d/php.ini
    working_dir: /var/www/html/
    links:
      - mysql
      - laravel
    ports:
      - "9000:9000"
    container_name: code

  laravel:
    build: ./laravel
    #volumesがローカルからコンテナにマウントされるディレクトリ
    volumes:
        #各自切り替える事
      - /Users/alberorana/api:/var/www/html/api
      - ./php/php.ini:/usr/local/etc/php/conf.d/php.ini
    working_dir: /var/www/html/
    links:
      - mysql
    ports:
      - "9001:9001"
    container_name: laravel

  mysql:
    image: mysql:5.7
    environment:
      #各自のMuSQLコンテナに合わせる事
      MYSQL_ROOT_PASSWORD: ****
      MYSQL_DATABASE: ****
      MYSQL_ROOT_USER: root
    ports:
      - "13306:3306"
    volumes_from:
      - data
    volumes:
      - ./misc/mysqld.cnf:/etc/mysql/mysql.conf.d/mysqld.cnf
    container_name: mysql

追記:ホストからhttpにて接続できる事は確認しております。
そして、イメージ画像に誤りがありました。
イメージ画像ではクライアント、APIサーバーに各々nginxがあるイメージですが、正しくは1つのnginxに両方のサーバーがあり、ドメインで振り分けている設定になります。
もちろん本番環境は各サーバーでIPアドレスもドメインも違うのですが、開発環境は1つのdocker-composeで完結させたいため、このような構成を検討している状態になります。

default.conf(nginx)

server {
    listen 80;
    index index.php index.html;
    server_name localhost;
    include       mime.types;
    rewrite ^/(css|js)/(.*)\.\d+\.(css|js)$ http://localhost/$1/$2.$3 redirect;
    root       /var/www/html/public_html;

    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ \.php$ {
        root       /var/www/html/public_html;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass code:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_param CI_ENV development;
        #各自切り替える事
        fastcgi_param SERVER_NAME uchida;
    }
    location ~* \.(ico|css|js|gif|jpe?g|png)(\?[0-9]+)?$ {
        root       /var/www/html/public_html;
        expires 0;
        access_log off;

        #rewrite ^/(css|js)/(.*)\.\d+\.(css|js)$ http://localhost/$1/$2.$3 redirect;
        sendfile off;
    }
}

server {
    listen 80;
    index index.php index.html;
    server_name api.localhost;
    include       mime.types;
    root       /var/www/html/api/public;

    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ \.php$ {
        root       /var/www/html/api/public;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass laravel:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_param CI_ENV development;
        #各自切り替える事
        fastcgi_param SERVER_NAME uchida;
    }
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+4

Nginxの設定について記載がないのではずすかもしれないですが、とりあえずコンテナ側のポートを80に統一しましょか。
あと、コンテナ間通信の前に、そもそもホストから各コンテナ(codeigniter, laravel)にhttpアクセスできます?
質問のスコープが広すぎるので、もう少しご自身で切り分けていただくと回答しやすいです。

 質問の修正を踏まえて追記

構成的に、codeからlaravelにhttpリクエストするのであれば別(nginx)コンテナ経由になるので、解決策として以下の二通りの方法が考えられます。

  1. extra_hostsを使用する
例:
services:
  php-fpm:
    ...
    extra_hosts:
      - "api.localhost:${DOCKER_HOST_IP}"


※${DOCKER_HOST_IP}=ホストのIPアドレス(docker0)

  1. aliasesを使用する
例:
services:
  nginx:
    ...
    networks:
        hoge:
         aliases:
          - api.localhost
networks:
  hoge:
    driver: "bridge"

未検証なのでその点ご容赦ください。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/04/06 08:32

    >てことはcodeとlaravelコンテナにnginx(web)は入っておらずphp, php-fpm(appのみ)が入っているのですね?
    はい、そのようになっておりまして、nginxコンテナから各アプリに振り分ける形にしております。

    キャンセル

  • 2018/04/06 08:51

    なるほど。
    そのような構成ですと、docker環境では少し工夫する必要がありますねー。
    ここに書くと可読性が悪くなるので回答欄に追記します。

    キャンセル

  • 2018/04/06 15:25

    Aliasで解決することができました!
    ご丁寧に回答いただき、誠にありがとうございます。

    キャンセル

+1

codeigniter のソースを見ると、 api.localhost を参照したいように見えますが、 codeigniter 自身はそのURLを解決できないと考えています。 laravel:9000 宛ならうまくいくのではないでしょうか?
// このような呼び出しがしたいわけではないと思いますが、切り分けのため

api.localhost で APIとして呼ぶとなると、、、
code の links を laravel に代えて "nginx:api.localhost" と設定するとうまくいきそうな気がします。

nginx -> codeigniter -> nginx -> laravel という経路になるはず。


nginx からだと laravel:9000 となっていてそれが取得できるのであれば
docker-compose の laravel の ports は "9001:9000" が正しいのではないでしょうか?

ports の書式は "ホスト側ポート:コンテナ側ポート" です。

ただ、nginx経由でアクセスできるようになったならホストにバインドする必要もなくなり、expose で内部公開用ポートとして 9000 を指定するだけでよいはずです。


もし本番と同じようにnginxを分割するのであれば、networksとホストにバインドするポートを整理するとできると思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/04/06 15:25

    ご回答ありがとうございました。
    >docker-compose の laravel の ports は "9001:9000" が正しいのではないでしょうか?
    こちらはその通りでございました。
    "nginx:api.localhost"だとdocker-compose upの時点でエラーになってしまったため、Aliasで解決いたしました。

    キャンセル

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

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