Docker - redimensionando nginx e php-fpm separadamente

10

Estou brincando com o docker e o docker-compose e tenho uma pergunta.

Atualmente, o meu docker-compose.yml tem esta aparência:

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

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

O aplicativo contém o php-fpm na porta 9000 e o código do meu aplicativo. Web é nginx com alguns bits de configuração.

Isso funciona como eu esperaria, no entanto, para conectar nginx a php-fpm eu tenho essa linha:

fastcgi_pass    app:9000;

Como posso efetivamente escalar isso? Se eu quisesse, por exemplo, ter um contêiner nginx em execução, mas três contêineres de aplicativos em execução, eu certamente teria três instâncias php-fpm tentando escutar na porta 9000.

Como posso ter cada instância do php-fpm em uma porta diferente, mas ainda sei onde elas estão na configuração do nginx a qualquer momento?

Estou adotando a abordagem errada?

Obrigado!

    
por JimBlizz 21.05.2015 / 10:26

4 respostas

5

Uma solução é adicionar mais instâncias do php-fpm ao seu arquivo de composição do docker e, em seguida, usar um nginx upstream, conforme mencionado nas outras respostas para o equilíbrio de carga entre elas. Isso é feito neste exemplo de repo docker-compose: link

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

Isso não é realmente ideal, pois será necessário alterar a configuração do nginx e o docker-compose.yml quando quiser aumentar ou diminuir a escala.

Observe que a porta 9000 é interna ao contêiner e não ao seu host real, portanto, não importa que você tenha vários contêineres php-fpm na porta 9000.

O Docker adquiriu a Tutum neste outono. Eles têm uma solução que combina um contêiner HAProxy com sua API para ajustar automaticamente a configuração do balanceador de carga para os contêineres em execução com balanceamento de carga. Essa é uma boa solução. Em seguida, o nginx aponta para o nome do host atribuído ao balanceador de carga. Talvez o Docker integre ainda mais esse tipo de solução em suas ferramentas após a aquisição do Tutum. Há um artigo sobre isso aqui: link

O tutum é atualmente um serviço pago. Rancher é um projeto de código aberto que fornece um recurso semelhante de balanceamento de carga. Eles também têm um "rancher-compose.yml" que pode definir o balanceamento de carga e o dimensionamento da configuração dos serviços no docker-compose.yml. link link

UPDATE 2017/03/06: usei um projeto chamado interlock que funciona com o Docker para atualizar automaticamente a configuração do nginx e reinicie-o. Veja também a resposta do @ iwaseatenbyagrue, que tem abordagens adicionais.

    
por 02.12.2015 / 22:09
1

Você pode usar um upstream para definir vários back-ends, conforme descrito aqui:

link

Você também deseja que a configuração seja atualizada sempre que novos back-ends morrerem / entrarem em serviço com algo como:

link

    
por 21.05.2015 / 10:41
0

No caso de seus contêineres Nginx e php-fpm estarem no mesmo host, você pode configurar um pequeno dnsmasq no host a ser usado pelo contêiner Nginx e execute um script para atualizar automaticamente o registro DNS quando o endereço IP do contêiner for alterado.

Escrevi um pequeno script para fazer isso (colado abaixo), que atualiza automaticamente o DNS registro que tem o mesmo nome que o nome dos contêineres e os aponta para os endereços IP dos contêineres:

#!/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

Em seguida, inicie seu contêiner nginx com --dns host-ip-address , em que host-ip-address é o endereço IP do host na interface docker0 .

Sua configuração do Nginx deve resolver nomes dinamicamente:

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

Referências:

Se o seu nginx e php-fpm estiverem em hosts diferentes, você pode tentar a resposta do @ smaj.

    
por 21.05.2015 / 23:00
0

Outra abordagem pode ser procurar algo como consul-template .

E, claro, em algum momento, o Kubernetes pode precisar ser mencionado.

No entanto, você poderia considerar uma abordagem um pouco mais de "pedaços de string e fita adesiva" examinando o que os eventos docking de consumo podem fazer por você (execute docker events --since 0 para obter uma amostra rápida).

Seria razoavelmente trivial ter um script olhando para esses eventos (tendo em mente que há vários pacotes de clientes disponíveis, incluindo python, go, etc), corrigindo um arquivo de configuração e recarregando o nginx (isto é, usando a consul- abordagem modelo, mas sem a necessidade de cônsul).

Para voltar à sua premissa original: enquanto os seus contêineres php-fpm forem iniciados com sua própria rede (ou seja, não compartilhando de outro contêiner, como o nginx), você poderá ter tantos contêineres escutando na porta 9000 como você quer - como eles têm IPs por contêiner, não há nenhum problema com o conflito de portas '.

Como você dimensiona isso provavelmente dependerá de qual é o seu objetivo / caso de uso final, mas uma coisa que você pode considerar é colocar o HAproxy entre o nginx e seus nós do php-fpm. Uma coisa que isso pode permitir é simplesmente nomear um intervalo (e possivelmente criar um docker network ) para seus servidores php-fpm (isto é, 172.18.0.0/24) e ter o HAproxy configurado para tentar usar qualquer IP dentro desse intervalo como um backend. Como o HAproxy tem verificações de saúde, ele pode identificar rapidamente quais endereços estão ativos e utilizá-los.

Veja link para uma discussão sobre como o nginx vs haproxy lida com upstreams .

A menos que você esteja usando uma rede docker dedicada para isso, você pode precisar fazer algum gerenciamento de IP manual para seus nós php-fpm.

    
por 03.03.2017 / 09:35