Docker Networking - nginx: Không tìm thấy máy chủ [khẩn cấp] ở thượng nguồn


98

Gần đây tôi đã bắt đầu chuyển sang các tính năng mạng của Docker 1.9 và Docker-Compose 1.5 để thay thế bằng cách sử dụng liên kết.

Cho đến nay với các liên kết, không có vấn đề gì với nginx kết nối với máy chủ fastcgi php5-fpm của tôi nằm ở một máy chủ khác trong một nhóm thông qua docker-comp. Tuy nhiên, mới đây khi tôi chạy vùng chứa docker-compose --x-networking upphp-fpm, mongo và nginx khởi động, tuy nhiên nginx thoát ngay lập tức với[emerg] 1#1: host not found in upstream "waapi_php_1" in /etc/nginx/conf.d/default.conf:16

Tuy nhiên, nếu tôi chạy lại lệnh docker-comp khi các vùng chứa php và mongo đang chạy (nginx đã thoát), nginx sẽ bắt đầu và hoạt động tốt từ đó trở đi.

Đây là docker-compose.ymltệp của tôi :

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

Đây là của tôi default.confcho nginx:

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

Làm cách nào để nginx hoạt động chỉ với một cuộc gọi soạn thư trên docker?


3
Tôi cũng gặp phải điều này. Tôi không chắc đó là lỗi với tệp soạn thảo hay lỗi với chính mạng docker.
thứ sáu

Câu trả lời:


26

Có thể sử dụng "volume_from" như một giải pháp thay thế cho đến khi tính năng depend_on (được thảo luận bên dưới) được giới thiệu. Tất cả những gì bạn phải làm là thay đổi tệp trình soạn thảo-docker của bạn như sau:

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

Một lưu ý lớn trong cách tiếp cận ở trên là khối lượng php được tiếp xúc với nginx, điều này không mong muốn. Nhưng hiện tại, đây là một cách giải quyết cụ thể cho từng docker có thể được sử dụng.

Tính năng depend_on Đây có lẽ sẽ là một câu trả lời trong tương lai. Bởi vì chức năng chưa được triển khai trong Docker (kể từ 1.9)

Có một đề xuất để giới thiệu "depend_on" trong tính năng mạng mới do Docker giới thiệu. Nhưng có một cuộc tranh luận kéo dài về cùng một @ https://github.com/docker/compose/issues/374 Do đó, sau khi nó được triển khai, tính năng depend_on có thể được sử dụng để yêu cầu khởi động vùng chứa, nhưng tại lúc này, bạn sẽ phải dùng đến một trong những cách sau:

  1. thực hiện nginx thử lại cho đến khi máy chủ php hoạt động - tôi thích cái này hơn
  2. sử dụng cách giải quyết volums_from như được mô tả ở trên - Tôi sẽ tránh sử dụng cách này, vì sự rò rỉ âm lượng vào các vùng chứa không cần thiết.

3
Điều này đã không sửa chữa nó cho tôi.
Gijs

@Gijs nếu bạn có thể đăng trường hợp chính xác của bạn là gì và điều gì không hiệu quả, ai đó có thể giúp đỡ trên diễn đàn.
Phani

4
volume_from không được dùng nữa
Roma Rush

Tôi đã gặp sự cố trong Azure App Service Docker Compose (xem trước) với điều này. Cũng phải đảm bảo rằng bất kỳ dịch vụ nào links:tôi đưa vào nginx đều sử dụng cùng tên với bản thân dịch vụ như - my-service:my-servicehoặc trong ví dụ này - mongo:mongo.
greg

29

Điều này có thể được giải quyết với depends_onchỉ thị đã đề cập vì nó được triển khai ngay bây giờ (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

Đã thử nghiệm thành công với:

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

Tìm thêm chi tiết trong tài liệu .

Ngoài ra còn có một bài viết rất thú vị dành riêng cho chủ đề này: Kiểm soát thứ tự khởi động trong Soạn


12

Bạn có thể đặt các chỉ thị max_fails và fail_timeout của nginx để chỉ ra rằng nginx nên thử lại số x yêu cầu kết nối tới vùng chứa trước khi không thực hiện được trên máy chủ ngược dòng.

Bạn có thể điều chỉnh hai con số này tùy theo cơ sở hạ tầng và tốc độ mà toàn bộ thiết lập đang diễn ra. Bạn có thể đọc thêm chi tiết về phần kiểm tra sức khỏe tại URL dưới đây: http://nginx.org/vi/docs/http/load_balancing.html

Sau đây là đoạn trích từ http://nginx.org/vi/docs/http/ngx_http_upstream_module.html#server max_fails=number

đặt số lần không thành công để giao tiếp với máy chủ sẽ xảy ra trong khoảng thời gian được đặt bởi tham số fail_timeout để coi máy chủ không khả dụng trong một khoảng thời gian cũng được đặt bởi tham số fail_timeout. Theo mặc định, số lần thử không thành công được đặt thành 1. Giá trị 0 vô hiệu hóa tính toán các lần thử. Điều gì được coi là cố gắng không thành công được xác định bởi các chỉ thị proxy_next_upstream, fastcgi_next_upstream, uwsgi_next_upstream, scgi_next_upstream và memcached_next_upstream.

fail_timeout=time

đặt thời gian trong đó số lần cố gắng giao tiếp với máy chủ không thành công được chỉ định sẽ xảy ra để coi máy chủ không khả dụng; và khoảng thời gian máy chủ sẽ được coi là không khả dụng. Theo mặc định, tham số được đặt thành 10 giây.

Để chính xác, tệp cấu hình nginx đã sửa đổi của bạn phải như sau (tập lệnh này giả định rằng tất cả các vùng chứa tối thiểu là 25 giây, nếu không, hãy thay đổi fail_timeout hoặc max_fails trong phần ngược dòng bên dưới): Lưu ý: Tôi đã không tự kiểm tra kịch bản, vì vậy bạn có thể thử!

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

Ngoài ra, theo Lưu ý sau đây từ docker ( https://github.com/docker/docker.github.io/blob/master/compose/networking.md#update-containers ), rõ ràng là logic thử lại để kiểm tra sức khỏe của các thùng chứa khác không thuộc trách nhiệm của người đóng tàu và thay vào đó, các thùng chứa phải tự kiểm tra sức khỏe.

Cập nhật vùng chứa

Nếu bạn thực hiện thay đổi cấu hình đối với một dịch vụ và chạy docker-soạn để cập nhật nó, vùng chứa cũ sẽ bị xóa và vùng chứa mới sẽ tham gia mạng theo một địa chỉ IP khác nhưng có cùng tên. Các vùng chứa đang chạy sẽ có thể tra cứu tên đó và kết nối với địa chỉ mới, nhưng địa chỉ cũ sẽ ngừng hoạt động.

Nếu bất kỳ thùng chứa nào có kết nối mở với thùng chứa cũ, chúng sẽ bị đóng lại. Người chứa có trách nhiệm phát hiện tình trạng này, tra cứu lại tên và kết nối lại.


3
Điều này sẽ không hoạt động. hãy đọc cảnh báo ở cuối phần này trong tài liệu nginx: "Nếu chỉ có một máy chủ duy nhất trong một nhóm, các thông số max_fails, fail_timeout và slow_start sẽ bị bỏ qua và một máy chủ như vậy sẽ không bao giờ được coi là không khả dụng."
Ferguzz

1
@Ferguzz đó là một cú bắt tốt. Một giải pháp khác là bạn có thể thêm hai mục nhập bí danh của cùng một vùng chứa để tạo một nhóm từ cùng một vùng chứa.
Phani

Là một giải pháp thay thế, tôi đã cung cấp trong câu hỏi tương tự, sử dụng "volume_from" để liên kết các vùng chứa và khiến chúng đợi cho đến khi các vùng chứa khác được tải. Điều này đang làm việc cho tôi.
Phani

7

Tôi tin rằng Nginx không tính đến trình giải quyết Docker (127.0.0.11), vì vậy, bạn có thể thử thêm:

resolver 127.0.0.11

trong tệp cấu hình nginx của bạn?


Thêm nhiều trình phân giải nhưresolver 127.0.0.11 8.8.8.8;
Leonardo Chaia

1
Không vì nó sẽ truy vấn theo kiểu vòng tròn như đã nêu trong tài liệu: Máy chủ định danh được truy vấn theo kiểu vòng tròn.
dalore

6

Nếu bạn bị mất để đọc bình luận cuối cùng. Tôi đã đạt được một giải pháp khác.

Vấn đề chính là cách bạn đặt tên các dịch vụ.

Trong trường hợp này, nếu trong của bạn docker-compose.yml, dịch vụ cho php được gọi là "api" hoặc một cái gì đó tương tự, bạn phải đảm bảo rằng trong tệp nginx.conf, dòng bắt đầu bằng fastcgi_passcó cùng tên với dịch vụ php. I Efastcgi_pass api:9000;


3

Tôi đã gặp vấn đề tương tự vì có hai mạng được xác định trong của tôi docker-compose.yml: một phụ trợ và một giao diện người dùng.
Khi tôi thay đổi điều đó để chạy các vùng chứa trên cùng một mạng mặc định, mọi thứ bắt đầu hoạt động tốt.


Điều này còn lâu mới trở thành câu trả lời.
dargmuesli

2

Gặp vấn đề tương tự và đã giải quyết nó. Vui lòng thêm dòng sau vào phần docker-compost.yml nginx:

links:
  - php:waapi_php_1

Máy chủ trong phần nginx config fastcgi_pass phải được liên kết bên trong cấu hình nginx docker-comp.yml.


1

Hai điều đáng nói:

  • Sử dụng cùng một cầu nối mạng
  • Sử dụng linksđể thêm phân giải máy chủ

Ví dụ của tôi:

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

Nếu bạn không chỉ định một cầu nối mạng đặc biệt, tất cả chúng sẽ sử dụng cùng một cầu nối mặc định.


1

Ngay từ cái nhìn đầu tiên, tôi đã bỏ qua, rằng dịch vụ "web" của tôi không thực sự bắt đầu, vì vậy đó là lý do tại sao nginx không thể tìm thấy bất kỳ máy chủ nào

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

này, tôi đang gặp vấn đề tương tự. Ứng dụng của tôi không chạy nên tôi gặp lỗi tương tự. tôi đã đặt uwsgi-file dưới dạng run.py trong app.ini mà lẽ ra phải chạy ứng dụng nhưng nó không xảy ra
isrj5

0

Với các liên kết, lệnh khởi động vùng chứa đang được thực thi. Không có liên kết, các vùng chứa có thể bắt đầu theo bất kỳ thứ tự nào (hoặc thực sự là tất cả cùng một lúc).

Tôi nghĩ rằng thiết lập cũ có thể gặp phải vấn đề tương tự, nếu vùng waapi_php_1chứa khởi động chậm.

Tôi nghĩ để làm cho nó hoạt động, bạn có thể tạo một tập lệnh entrypoint nginx để thăm dò ý kiến ​​và đợi vùng chứa php được khởi động và sẵn sàng.

Tôi không chắc liệu nginx có cách nào để tự động thử lại kết nối với ngược dòng hay không, nhưng nếu có, đó sẽ là một lựa chọn tốt hơn.


Và làm cách nào để thực hiện thăm dò ý kiến?
Attila Szeremi vào


0

Có lẽ lựa chọn tốt nhất để tránh các vấn đề liên kết vùng chứa là các tính năng mạng của docker

Nhưng để làm cho việc này hoạt động, docker tạo các mục nhập trong / etc / hosts cho mỗi vùng chứa từ các tên được chỉ định cho mỗi vùng chứa.

với docker-compile --x-networking -up giống như [docker_compose_folder] - [dịch vụ] - [số_tăng_số]

Để không phụ thuộc vào những thay đổi bất ngờ trong những tên này, bạn nên sử dụng tham số

container_name

trong docker-compo.yml của bạn như sau:

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

Đảm bảo rằng đó là cùng một tên được chỉ định trong tệp cấu hình của bạn cho dịch vụ này. Tôi khá chắc rằng có nhiều cách tốt hơn để làm điều này, nhưng đó là một cách tiếp cận tốt để bắt đầu.


0

Cách giải quyết của tôi (sau nhiều lần thử và sai):

  • Để giải quyết vấn đề này, tôi phải lấy tên đầy đủ của vùng chứa Docker 'ngược dòng', được tìm thấy bằng cách chạy docker network inspect my-special-docker-networkvà nhận toàn bộ namethuộc tính của vùng chứa ngược dòng như:

    "Containers": {
         "39ad8199184f34585b556d7480dd47de965bc7b38ac03fc0746992f39afac338": {
              "Name": "my_upstream_container_name_1_2478f2b3aca0",
    
  • Sau đó, sử dụng nó trong my-network.local.conftệp NGINX trong locationkhối thuộc proxy_passtính: (Lưu ý thêm GUID vào tên vùng chứa):

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

Trái ngược với hoạt động trước đây, nhưng bây giờ đã bị hỏng:

    location / {
        proxy_pass http://my_upstream_container_name_1:3000

Nguyên nhân rất có thể là một thay đổi gần đây đối với Docker Compose, trong lược đồ đặt tên mặc định của họ cho vùng chứa, như được liệt kê ở đây .

Điều này dường như đang xảy ra với tôi và nhóm của tôi tại nơi làm việc, với các phiên bản mới nhất của nginxhình ảnh Docker :

  • Tôi đã mở các vấn đề với chúng trên docker / soạn GitHub tại đây

0

(mới sử dụng nginx) Trong trường hợp của tôi, đó là tên thư mục sai

Đối với cấu hình

upstream serv {
    server ex2_app_1:3000;
}

đảm bảo rằng thư mục ứng dụng nằm trong thư mục ex2:

ex2 / app / ...


0

lỗi này xuất hiện với tôi vì php-fpmhình ảnh của tôi đã được bật cronvà tôi không biết tại sao


0

Vấn đề của tôi là tôi đã quên chỉ định bí danh mạng trong docker-compos.yml trong php-fpm

    networks:
      - u-online

Nó hoạt động tốt!

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

-1

Thêm các liên kết vào cấu hình vùng chứa nginx của bạn.

Bạn phải hiển thị vùng phpchứa đối với vùng nginxchứa.

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

1
Tôi biết về các liên kết, tuy nhiên Docker đánh dấu chúng không được dùng nữa trong phiên bản 1.9 ra mắt cách đây một tuần để ủng hộ việc sử dụng mạng của Docker. Tôi muốn một giải pháp sử dụng điều đó, một phần vì các liên kết có vấn đề với liên kết vòng mà mạng không nên có.
Attila Szeremi

1
Trong CHANGELOG.md, tôi không thấy linkbị phản đối. Tui bỏ lỡ điều gì vậy?
nessuno

Tôi cũng không thấy điều đó trong đó; tuy nhiên khi tôi chạy docker-compose --x-networking upvới các liên kết theo quy định tại của tôi docker-compose.yml, tôi nhận được cảnh báo này rõ ràng: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

Ok, tôi đã tìm thấy nơi không dùng nữa. Ý tưởng duy nhất tôi có là: bạn có docker-compose.ymltập tin trong một thư mục có tên waapikhông?
nessuno

Vâng, đó là trong một thư mục có tênwaapi
Attila Szeremi
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.