Docker-nginx와 php-fpm을 별도로 스케일링


11

도커 및 도커 작성으로 놀고 있었고 질문이 있습니다.

현재 내 docker-compose.yml은 다음과 같습니다.

app:
    image: myname/php-app
    volumes:
        - /var/www
    environment:
        <SYMFONY_ENVIRONMENT>: dev

web:
    image: myname/nginx
    ports:
        - 80
    links:
        - app
    volumes_from:
        - app

응용 프로그램은 포트 9000에 PHP-fpm과 내 응용 프로그램 코드가 포함되어 있습니다. 웹은 몇 비트의 구성으로 nginx입니다.

이것은 nginx를 php-fpm에 연결하기 위해 어떻게 기대할 수 있는지 기능합니다.

fastcgi_pass    app:9000;

어떻게 효과적으로 확장 할 수 있습니까? 예를 들어 하나의 nginx 컨테이너를 실행하고 3 개의 앱 컨테이너를 실행하려면 3 개의 php-fpm 인스턴스가 모두 포트 9000에서 수신 대기해야합니다.

각각의 php-fpm 인스턴스를 다른 포트에 어떻게 가질 수 있지만 주어진 시간에 내 nginx 설정의 위치를 ​​여전히 알 수 있습니까?

내가 잘못된 접근법을 취하고 있습니까?

감사!

답변:


5

한 가지 해결책은 docker-compose 파일에 추가 php-fpm 인스턴스를 추가 한 다음 다른 답변에서 언급 한 것처럼 nginx 업스트림을 사용하여 인스턴스 간로드 균형을 조정하는 것입니다. 이것은이 예제 docker-compose repo에서 수행됩니다 : https://github.com/iamyojimbo/docker-nginx-php-fpm/blob/master/nginx/nginx.conf#L137

upstream php {
    #If there's no directive here, then use round_robin.
    #least_conn;
    server dockernginxphpfpm_php1_1:9000;
    server dockernginxphpfpm_php2_1:9000;
    server dockernginxphpfpm_php3_1:9000;
}

확장 또는 축소하려는 경우 nginx 구성 및 docker-compose.yml을 변경해야하므로 이것은 이상적이지 않습니다.

9000 포트는 실제 호스트가 아닌 컨테이너 내부에 있으므로 포트 9000에 여러 개의 php-fpm 컨테이너가 있는지는 중요하지 않습니다.

Docker는 올 가을 Tutum을 인수했습니다. HAProxy 컨테이너와 API를 결합하여로드 밸런서 구성을 실행중인 컨테이너에 맞게 자동으로 조정하는 솔루션이 있습니다. 좋은 해결책입니다. 그런 다음 nginx는로드 밸런서에 할당 된 호스트 이름을 가리 킵니다. Docker는 Tutum 인수 후 이러한 유형의 솔루션을 도구에 추가로 통합 할 것입니다. 여기에 대한 기사가 있습니다. https://web.archive.org/web/20160628133445/https://support.tutum.co/support/solutions/articles/5000050235-load-balancing-a-web-service

Tutum은 현재 유료 서비스입니다. Rancher는 유사한로드 밸런싱 기능을 제공하는 오픈 소스 프로젝트입니다. 또한 docker-compose.yml에서 서비스 설정의로드 균형 조정 및 확장을 정의 할 수있는 "rancher-compose.yml"이 있습니다. http://rancher.com/the-magical-moment-when-container-load-balancing-meets-service-discovery/ http://docs.rancher.com/rancher/concepts/#load-balancer

2017/03/06 업데이트 : Docker와 함께 작동하는 interlock 이라는 프로젝트를 사용 하여 nginx 구성을 자동으로 업데이트하고 다시 시작했습니다. 또한 추가 접근법이있는 @iwaseatenbyagrue의 답변 을 참조하십시오 .



0

Nginx 및 php-fpm 컨테이너가 동일한 호스트 에있는 경우 Nginx 컨테이너가 사용할 호스트에서 작은 dnsmasq 인스턴스를 구성 하고 컨테이너의 IP 주소가있을 때 자동으로 DNS 레코드를 업데이트하도록 스크립트를 실행할 수 있습니다 변경되었습니다.

컨테이너 이름과 동일한 이름의 DNS 레코드를 자동으로 업데이트하고 컨테이너의 IP 주소를 가리키는 작은 스크립트 를 작성 했습니다 (아래 붙여 넣기).

#!/bin/bash

# 10 seconds interval time by default
INTERVAL=${INTERVAL:-10}

# dnsmasq config directory
DNSMASQ_CONFIG=${DNSMASQ_CONFIG:-.}

# commands used in this script
DOCKER=${DOCKER:-docker}
SLEEP=${SLEEP:-sleep}
TAIL=${TAIL:-tail}

declare -A service_map

while true
do
    changed=false
    while read line
    do
        name=${line##* }
        ip=$(${DOCKER} inspect --format '{{.NetworkSettings.IPAddress}}' $name)
        if [ -z ${service_map[$name]} ] || [ ${service_map[$name]} != $ip ] # IP addr changed
        then
            service_map[$name]=$ip
            # write to file
            echo $name has a new IP Address $ip >&2
            echo "host-record=$name,$ip"  > "${DNSMASQ_CONFIG}/docker-$name"
            changed=true
        fi
    done < <(${DOCKER} ps | ${TAIL} -n +2)

    # a change of IP address occured, restart dnsmasq
    if [ $changed = true ]
    then
        systemctl restart dnsmasq
    fi

    ${SLEEP} $INTERVAL
done

그런 다음 귀하의 nginx 컨테이너 시작 --dns host-ip-address, host-ip-address인터페이스의 호스트의 IP 주소입니다 docker0.

귀하의 Nginx의 구성은 동적으로 이름을 확인한다 :

server {
  resolver host-ip-address;
  listen 80;
  server_name @server_name@;
  root /var/www/@root@;
  index index.html index.htm index.php;

  location ~ ^(.+?\.php)(/.*)?$ {
    try_files $uri =404;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$1;
    set $backend "@fastcgi_server@";
    fastcgi_pass $backend;
  }
}

참고 문헌 :

nginx와 php-fpm이 다른 호스트에 있다면 @smaj의 답변을 시도 할 수 있습니다.


0

또 다른 접근법은 영사 템플릿 과 같은 것을 살펴 보는 것 입니다.

물론 어떤 시점에서는 Kubernetes 를 언급해야 할 수도 있습니다.

그러나 소비하는 도커 이벤트가 수행 할 수있는 작업 ( docker events --since 0빠른 샘플 실행) 을 살펴보면 약간 더 많은 '비트 및 덕트 테이프 비트'접근법을 고려할 수 있습니다 .

이러한 이벤트를 살펴 보거나 (python, go 등을 포함하여 여러 클라이언트 패키지를 사용할 수 있음을 염두에두고) 구성 파일을 수정하고 nginx를 다시로드하는 등의 스크립트를 작성하는 것은 상당히 사소한 일입니다. 그러나 영사 필요 없음).

그래도 원래 전제로 돌아가려면 : php-fpm 컨테이너가 자체 네트워크로 시작되는 한 (즉, nginx와 같은 다른 컨테이너의 컨테이너를 공유하지 않는 한) 많은 컨테이너가 포트에서 수신 대기 할 수 있습니다 9000-컨테이너 당 IP가 있으므로 포트 '충돌'에 문제가 없습니다.

이것을 확장하는 방법은 궁극적 인 목표 / 사용 사례에 따라 다르지만 nginx와 php-fpm 노드 사이에 HAproxy를 배치하는 것이 좋습니다. 이것이 할 수있는 한 가지 일은 단순히 docker networkphp-fpm 서버 (예 : 172.18.0.0/24) 의 범위를 지정 하고을 생성하고 해당 범위 내의 모든 IP를 백엔드로 사용하도록 HAproxy를 구성하는 것입니다 . HAproxy에는 상태 확인 기능이 있으므로 사용중인 주소를 빠르게 식별하여 사용할 수 있습니다.

nginx vs haproxy가 업스트림을 처리하는 방법에 대한 자세한 내용은 /programming/1358198/nginx-removing-upstream-servers-from-pool 을 참조 하십시오 .

이를 위해 전용 도커 네트워크를 사용하지 않는 한, php-fpm 노드에 대한 수동 IP 관리를 수행해야 할 수도 있습니다 .


0

이 게시물은 2015 년부터 왔으며 괴로움을 느끼고 있지만 (미안한 커뮤니티)이 시점에서 추가하는 것이 가치가 있다고 생각합니다.

Docker로 작업 할 때 요즘 Kubernetes가 언급 된 이후로 Kubernetes 또는 Docker Swarm을 사용 하여이 문제를 매우 쉽게 해결할 수 있습니다. 두 오케 스트레이터 모두 도커 노드 (하나의 노드 =도 커가있는 하나의 서버)를 가져와 서비스를 배포 할 수 있으며 오버레이 네트워크를 사용하여 포트 문제를 관리합니다.

Docker Swarm에 더 정통한 것처럼 단일 Docker 노드가 있다고 가정하면이 문제에 접근하는 방법입니다.

떼를 초기화하십시오 :

docker swarm init

프로젝트 루트에 cd

cd some/project/root

docker-compose를 사용하는 대신 docker-compose.yml에서 swarm stack을 만듭니다.

docker stack deploy -c docker-compose.yml myApp

그러면 "myApp"라는 도커 떼 서비스 스택이 만들어지고 포트가 관리됩니다. 즉, docker-compose 파일의 php-fpm 서비스에 "port : 9000 : 9000"정의를 하나만 추가하면 php-fpm 서비스를 3 개의 인스턴스로 확장 할 수 있습니다. 추가 작업없이 세 인스턴스간에 요청을 자동으로로드 밸런싱합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.