Docker Networking - nginx: host [emerg] tidak ditemukan di upstream

99

Saya baru-baru ini mulai bermigrasi ke fitur jaringan Docker 1.9 dan Docker-Compose 1.5 untuk mengganti menggunakan tautan.

Sejauh ini dengan tautan tidak ada masalah dengan nginx menghubungkan ke server fastcgi php5-fpm saya yang terletak di server berbeda dalam satu grup melalui docker-compose. Baru-baru ini ketika saya menjalankan docker-compose --x-networking upwadah php-fpm, mongo dan nginx saya boot, namun nginx langsung berhenti dengan[emerg] 1#1: host not found in upstream "waapi_php_1" in /etc/nginx/conf.d/default.conf:16

Namun, jika saya menjalankan perintah docker-compose lagi saat wadah php dan mongo berjalan (nginx keluar), nginx mulai dan berfungsi dengan baik sejak saat itu.

Ini docker-compose.ymlfile saya :

nginx:
  image: nginx
  ports:
    - "42080:80"
  volumes:
    - ./config/docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro

php:
  build: config/docker/php
  ports:
    - "42022:22"
  volumes:
    - .:/var/www/html
  env_file: config/docker/php/.env.development

mongo:
  image: mongo
  ports:
    - "42017:27017"
  volumes:
    - /var/mongodata/wa-api:/data/db
  command: --smallfiles

Ini default.confuntuk nginx saya :

server {
    listen  80;

    root /var/www/test;

    error_log /dev/stdout debug;
    access_log /dev/stdout;

    location / {
        # try to serve file directly, fallback to app.php
        try_files $uri /index.php$is_args$args;
    }

    location ~ ^/.+\.php(/|$) {
        # Referencing the php service host (Docker)
        fastcgi_pass waapi_php_1:9000;

        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;

        # We must reference the document_root of the external server ourselves here.
        fastcgi_param SCRIPT_FILENAME /var/www/html/public$fastcgi_script_name;

        fastcgi_param HTTPS off;
    }
}

Bagaimana saya bisa membuat nginx bekerja hanya dengan satu panggilan docker-compose?

Attila Szeremi
sumber
3
Saya mengalami ini juga. Saya tidak yakin apakah itu kesalahan dengan file penulisan, atau bug dengan jaringan buruh pelabuhan itu sendiri.
jrdn

Jawaban:

26

Ada kemungkinan untuk menggunakan "volumes_from" sebagai solusi sampai fitur depend_on (dibahas di bawah) diperkenalkan. Yang harus Anda lakukan adalah mengubah file docker-compose Anda seperti di bawah ini:

nginx:
  image: nginx
  ports:
    - "42080:80"
  volumes:
    - ./config/docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
  volumes_from:
    - php

php:
  build: config/docker/php
  ports:
    - "42022:22"
  volumes:
    - .:/var/www/html
  env_file: config/docker/php/.env.development

mongo:
  image: mongo
  ports:
    - "42017:27017"
  volumes:
    - /var/mongodata/wa-api:/data/db
  command: --smallfiles

Satu peringatan besar dalam pendekatan di atas adalah bahwa volume php terkena nginx, yang tidak diinginkan. Namun saat ini, ini adalah salah satu solusi khusus buruh pelabuhan yang dapat digunakan.

fitur dependent_on Ini mungkin jawaban yang futuristik. Karena fungsinya belum diimplementasikan di Docker (mulai 1.9)

Ada usulan untuk memperkenalkan "depend_on" di fitur jaringan baru yang diperkenalkan oleh Docker. Tetapi ada perdebatan panjang tentang hal yang sama @ https://github.com/docker/compose/issues/374 Oleh karena itu, setelah diimplementasikan, fitur depend_on dapat digunakan untuk memesan permulaan kontainer, tetapi di saat ini, Anda harus menggunakan salah satu dari yang berikut:

  1. buat nginx coba lagi sampai server php habis - Saya lebih suka yang ini
  2. gunakan solusi volums_from seperti yang dijelaskan di atas - Saya akan menghindari penggunaan ini, karena kebocoran volume ke wadah yang tidak perlu.
Phani
sumber
3
Ini tidak memperbaikinya untuk saya.
Gijs
@Gijs jika Anda dapat memposting apa kasus Anda sebenarnya dan apa yang tidak berhasil, seseorang dapat membantu di forum.
Phani
4
volumes_from tidak digunakan lagi
Roma Rush
Saya mengalami masalah di Azure App Service Docker Compose (pratinjau) dengan ini. Juga harus memastikan bahwa setiap yang links:saya sertakan dalam nginx menggunakan nama yang sama dengan layanan itu sendiri seperti - my-service:my-serviceatau dalam contoh ini - mongo:mongo.
greg
29

Ini dapat diselesaikan dengan depends_onarahan yang disebutkan sejak diterapkan sekarang (2016):

version: '2'
  services:
    nginx:
      image: nginx
      ports:
        - "42080:80"
      volumes:
        - ./config/docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
      depends_on:
        - php

    php:
      build: config/docker/php
      ports:
        - "42022:22"
      volumes:
        - .:/var/www/html
      env_file: config/docker/php/.env.development
      depends_on:
        - mongo

    mongo:
      image: mongo
      ports:
        - "42017:27017"
      volumes:
        - /var/mongodata/wa-api:/data/db
      command: --smallfiles

Berhasil diuji dengan:

$ docker-compose version
docker-compose version 1.8.0, build f3628c7

Temukan detail lebih lanjut di dokumentasi .

Ada juga artikel yang sangat menarik yang didedikasikan untuk topik ini: Mengontrol urutan startup di Compose

czerasz.dll
sumber
12

Anda dapat menyetel perintah max_fails dan fail_timeout dari nginx untuk menunjukkan bahwa nginx harus mencoba ulang x jumlah permintaan koneksi ke container sebelum gagal pada ketidaktersediaan server upstream.

Anda dapat menyetel kedua angka ini sesuai infrastruktur Anda dan kecepatan seluruh penyiapan akan datang. Anda dapat membaca lebih banyak detail tentang bagian health check di URL di bawah ini: http://nginx.org/en/docs/http/load_balancing.html

Berikut adalah kutipan dari http://nginx.org/en/docs/http/ngx_http_upstream_module.html#server max_fails=number

menetapkan jumlah upaya gagal untuk berkomunikasi dengan server yang harus terjadi dalam durasi yang ditetapkan oleh parameter fail_timeout untuk mempertimbangkan server tidak tersedia untuk durasi yang juga ditetapkan oleh parameter fail_timeout. Secara default, jumlah upaya yang gagal diatur ke 1. Nilai nol menonaktifkan penghitungan upaya. Apa yang dianggap sebagai upaya yang tidak berhasil ditentukan oleh arahan proxy_next_upstream, fastcgi_next_upstream, uwsgi_next_upstream, scgi_next_upstream, dan memcached_next_upstream.

fail_timeout=time

menetapkan waktu selama sejumlah upaya komunikasi yang tidak berhasil untuk berkomunikasi dengan server harus dilakukan untuk mempertimbangkan server tidak tersedia; dan jangka waktu server dianggap tidak tersedia. Secara default, parameter disetel ke 10 detik.

Tepatnya file konfigurasi nginx Anda yang dimodifikasi harus seperti berikut (skrip ini mengasumsikan bahwa semua kontainer naik setidaknya 25 detik, jika tidak, silakan ubah fail_timeout atau max_fails di bawah bagian hulu): Catatan: Saya tidak uji skripnya sendiri, jadi Anda bisa mencobanya!

upstream phpupstream {
   server waapi_php_1:9000 fail_timeout=5s max_fails=5;
}
server {
    listen  80;

    root /var/www/test;

    error_log /dev/stdout debug;
    access_log /dev/stdout;

    location / {
        # try to serve file directly, fallback to app.php
        try_files $uri /index.php$is_args$args;
    }

    location ~ ^/.+\.php(/|$) {
        # Referencing the php service host (Docker)
        fastcgi_pass phpupstream;

        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;

        # We must reference the document_root of the external server ourselves here.
        fastcgi_param SCRIPT_FILENAME /var/www/html/public$fastcgi_script_name;

        fastcgi_param HTTPS off;
    }
}

Selain itu, sesuai Catatan berikut dari buruh pelabuhan ( https://github.com/docker/docker.github.io/blob/master/compose/networking.md#update-containers ), terbukti bahwa logika coba lagi untuk memeriksa Kesehatan dari container lain bukanlah tanggung jawab buruh B / M dan sebaliknya container tersebut harus melakukan health check sendiri.

Memperbarui kontainer

Jika Anda membuat perubahan konfigurasi pada layanan dan menjalankan docker-compose untuk memperbaruinya, container lama akan dihapus dan container baru akan bergabung dengan jaringan di bawah alamat IP yang berbeda tetapi dengan nama yang sama. Penampung yang berjalan akan dapat mencari nama itu dan terhubung ke alamat baru, tetapi alamat lama akan berhenti berfungsi.

Jika ada kontainer yang memiliki koneksi terbuka ke kontainer lama, mereka akan ditutup. Merupakan tanggung jawab penampung untuk mendeteksi kondisi ini, mencari namanya lagi, dan menyambungkan kembali.

Phani
sumber
3
Ini tidak akan berhasil. baca peringatan di akhir bagian ini di dokumen nginx: "Jika hanya ada satu server dalam grup, parameter max_fails, fail_timeout dan slow_start diabaikan, dan server seperti itu tidak akan pernah dianggap tidak tersedia."
Ferguzz
1
@Ferguzz itu tangkapan yang bagus. Sebagai solusinya, Anda dapat menambahkan dua entri alias dari penampung yang sama untuk membuat grup dari penampung yang sama.
Phani
Sebagai solusi alternatif, saya telah menyediakan dalam pertanyaan yang sama gunakan "volumes_from" untuk menautkan wadah dan membuatnya menunggu hingga wadah lain dimuat. Ini bekerja untuk saya.
Phani
7

Saya percaya Nginx tidak menggunakan akun Docker resolver (127.0.0.11), jadi tolong, bisakah Anda mencoba menambahkan:

resolver 127.0.0.11

di file konfigurasi nginx Anda?

Thomas Decaux
sumber
Tambahkan beberapa resolver sepertiresolver 127.0.0.11 8.8.8.8;
Leonardo Chaia
1
Tidak, karena akan melakukan kueri dalam round robin seperti yang dinyatakan dalam dokumen: Server nama ditanyai dengan cara round-robin.
dalore
6

Jika Anda begitu tersesat untuk membaca komentar terakhir. Saya telah mencapai solusi lain.

Masalah utamanya adalah cara Anda menamai nama layanan.

Dalam kasus ini, jika dalam Anda docker-compose.yml, layanan untuk php disebut "api" atau semacamnya, Anda harus memastikan bahwa di dalam file nginx.conf, baris yang diawali dengan fastcgi_passmemiliki nama yang sama dengan layanan php. yaitufastcgi_pass api:9000;

julian
sumber
3

Saya memiliki masalah yang sama karena ada dua jaringan yang ditentukan di saya docker-compose.yml: satu backend dan satu frontend.
Ketika saya mengubahnya untuk menjalankan kontainer di jaringan default yang sama semuanya mulai berfungsi dengan baik.

smola
sumber
Ini jauh dari jawaban.
dargmuesli
2

Memiliki masalah yang sama dan menyelesaikannya. Silakan tambahkan baris berikut ke bagian nginx docker-compose.yml:

links:
  - php:waapi_php_1

Host di bagian fastcgi_pass config nginx harus ditautkan di dalam konfigurasi nginx docker-compose.yml.

st0at
sumber
1

Dua hal yang perlu disebutkan:

  • Menggunakan jembatan jaringan yang sama
  • Menggunakan linksuntuk menambahkan resolusi host

Contoh saya:

version: '3'
services:
  mysql:
    image: mysql:5.7
    restart: always
    container_name: mysql
    volumes:
      - ./mysql-data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: tima@123
    network_mode: bridge
  ghost:
    image: ghost:2
    restart: always
    container_name: ghost
    depends_on:
      - mysql
    links:
      - mysql
    environment:
      database__client: mysql
      database__connection__host: mysql
      database__connection__user: root
      database__connection__password: xxxxxxxxx
      database__connection__database: ghost
      url: https://www.itsfun.tk
    volumes:
      - ./ghost-data:/var/lib/ghost/content
    network_mode: bridge
  nginx:
    image: nginx
    restart: always
    container_name: nginx
    depends_on:
      - ghost
    links:
      - ghost
    ports:
      - "80:80"
      - "443:443"
    volumes:
       - ./nginx/nginx.conf:/etc/nginx/nginx.conf
       - ./nginx/conf.d:/etc/nginx/conf.d
       - ./nginx/letsencrypt:/etc/letsencrypt
    network_mode: bridge

Jika Anda tidak menentukan jembatan jaringan khusus, semuanya akan menggunakan jembatan default yang sama.

NOZUONOHIGH
sumber
1

Pada pandangan pertama, saya melewatkan, bahwa layanan "web" saya tidak benar-benar dimulai, jadi itu sebabnya nginx tidak dapat menemukan host apa pun

web_1    | python3: can't open file '/var/www/app/app/app.py': [Errno 2] No such file or directory
web_1 exited with code 2
nginx_1  | [emerg] 1#1: host not found in upstream "web:4044" in /etc/nginx/conf.d/nginx.conf:2
Alveona
sumber
hai saya mengalami masalah yang sama. Aplikasi saya tidak berjalan jadi saya mendapatkan kesalahan yang sama. saya telah meletakkan uwsgi-file sebagai run.py di app.ini yang seharusnya menjalankan aplikasi tetapi tidak terjadi
isrj5
0

Dengan tautan, ada urutan startup penampung yang diberlakukan. Tanpa tautan, kontainer dapat dimulai dalam urutan apa pun (atau benar-benar sekaligus).

Saya pikir penyiapan lama bisa saja mengalami masalah yang sama, jika waapi_php_1penampung lambat untuk memulai.

Saya pikir untuk membuatnya berfungsi, Anda dapat membuat skrip entrypoint nginx yang melakukan polling dan menunggu wadah php dimulai dan siap.

Saya tidak yakin apakah nginx memiliki cara untuk mencoba kembali koneksi ke upstream secara otomatis, tetapi jika ya, itu akan menjadi opsi yang lebih baik.

dnephin
sumber
Dan bagaimana cara melakukan polling?
Attila Szeremi
0

Mungkin pilihan terbaik untuk menghindari masalah penautan kontainer adalah fitur jaringan buruh pelabuhan

Tetapi untuk membuat ini bekerja, buruh pelabuhan membuat entri di / etc / hosts untuk setiap kontainer dari nama yang diberikan ke setiap kontainer.

dengan docker-compose --x-networking -up adalah sesuatu seperti [docker_compose_folder] - [service] - [incremental_number]

Agar tidak bergantung pada perubahan tak terduga dalam nama ini, Anda harus menggunakan parameter

container_name

di docker-compose.yml Anda sebagai berikut:

php:
      container_name: waapi_php_1
      build: config/docker/php
      ports:
        - "42022:22"
      volumes:
        - .:/var/www/html
      env_file: config/docker/php/.env.development

Pastikan bahwa itu adalah nama yang sama yang diberikan di file konfigurasi Anda untuk layanan ini. Saya cukup yakin ada cara yang lebih baik untuk melakukan ini, tetapi ini adalah pendekatan yang baik untuk memulai.

JorelC
sumber
0

Solusi Saya (setelah banyak trial and error):

  • Untuk mengatasi masalah ini, saya harus mendapatkan nama lengkap dari kontainer Docker 'upstream', yang ditemukan dengan menjalankan docker network inspect my-special-docker-networkdan mendapatkan nameproperti lengkap dari kontainer upstream seperti:

    "Containers": {
         "39ad8199184f34585b556d7480dd47de965bc7b38ac03fc0746992f39afac338": {
              "Name": "my_upstream_container_name_1_2478f2b3aca0",
    
  • Kemudian gunakan ini di my-network.local.conffile NGINX di locationblok proxy_passproperti: (Perhatikan penambahan GUID ke nama wadah):

    location / {
        proxy_pass http://my_upsteam_container_name_1_2478f2b3aca0:3000;
    

Berbeda dengan yang sebelumnya berfungsi, tetapi sekarang rusak:

    location / {
        proxy_pass http://my_upstream_container_name_1:3000

Kemungkinan besar penyebabnya adalah perubahan terbaru pada Docker Compose, dalam skema penamaan default untuk container, seperti yang tercantum di sini .

Ini sepertinya terjadi pada saya dan tim saya di tempat kerja, dengan versi terbaru dari nginximage Docker :

  • Saya telah membuka masalah dengan mereka di buruh pelabuhan / menulis GitHub di sini
arcadia_168
sumber
0

(baru mengenal nginx) Dalam kasus saya, itu adalah nama folder yang salah

Untuk config

upstream serv {
    server ex2_app_1:3000;
}

pastikan folder aplikasi ada di folder ex2:

ex2 / app / ...

vijeth.ag
sumber
0

kesalahan ini muncul pada saya karena php-fpmgambar saya diaktifkan cron, dan saya tidak tahu mengapa

Ruan Nawe
sumber
0

Masalah saya adalah saya lupa menentukan alias jaringan di docker-compose.yml di php-fpm

    networks:
      - u-online

Ini bekerja dengan baik!

version: "3"
services:

  php-fpm:
    image: php:7.2-fpm
    container_name: php-fpm
    volumes:           
      - ./src:/var/www/basic/public_html
    ports:
      - 9000:9000
    networks:
      - u-online
      
  nginx: 
    image: nginx:1.19.2
    container_name: nginx   
    depends_on:
      - php-fpm       
    ports:
      - "80:8080"
      - "443:443"
    volumes:
      - ./docker/data/etc/nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf
      - ./docker/data/etc/nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./src:/var/www/basic/public_html
    networks:
      - u-online

#Docker Networks
networks:
  u-online:
    driver: bridge
Юрий Светлов
sumber
-1

Tambahkan bagian tautan ke konfigurasi wadah nginx Anda.

Anda harus menampilkan phpwadah ke nginxwadah.

nginx:
  image: nginx
  ports:
    - "42080:80"
  volumes:
    - ./config/docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
  links:
    - php:waapi_php_1
nessuno
sumber
1
Saya tahu tentang tautan, namun Docker menandainya tidak berlaku lagi di versi 1.9 yang keluar seminggu yang lalu untuk menggunakan jaringan Docker. Saya ingin solusi yang menggunakan itu, sebagian karena tautan memiliki masalah dengan tautan melingkar yang seharusnya tidak dimiliki jaringan.
Attila Szeremi
1
Di CHANGELOG.md saya tidak melihat linkadanya penghentian. Apakah saya melewatkan sesuatu?
nessuno
Aku juga tidak melihatnya di sana; Namun ketika saya menjalankan docker-compose --x-networking updengan tautan yang ditentukan dalam saya docker-compose.yml, saya mendapatkan peringatan yang jelas ini:WARNING: "nginx" defines links, which are not compatible with Docker networking and will be ignored. Future versions of Docker will not support links - you should remove them for forwards-compatibility.
Attila Szeremi
Oke saya menemukan di mana penghentian itu. Satu-satunya ide yang saya miliki adalah: apakah Anda docker-compose.ymlmengajukan dalam folder bernama waapi?
nessuno
Ya, ini ada dalam folder bernamawaapi
Attila Szeremi