Docker: execute Cronjob para contêiner diferente

Estou procurando as melhores práticas sobre como executar cronjobs para meu contêiner php fpm.

Agora correndo:

  • Nginx Container
  • Php fpm Container
  • MySQL Container

Agora eu adoraria ter outro contêiner em execução chamado "Cronjob Container" que exec é um script dentro do meu contêiner PHP FPM (preciso de algumas dependências do PHP ).

Então, três soluções possíveis:

1.) Executando um próprio contêiner

Eu adoraria usar esta solução!

Seria bom ter um contêiner executando CRON onde eu sou capaz de ( de alguma forma ) chamar docker exec no meu contêiner php fpm... Ou ter outra maneira.

2.) Executando CRON dentro do contêiner PHP

Isso seria bom, mas não é a melhor prática. Eu poderia iniciar um segundo processo dentro do meu contêiner php fpm executando cron. Isso funcionaria, mas não tenho certeza se é com quem você deve trabalhar no docker.

3.) Executando Hosts Cron

Isso seria cruel. Eu precisaria encontrar o processID e containerID de um determinado caminho e, em seguida, executar Docker exec. Mas este é mais ou menos o meu último caminho... E eu odeio Gerenciar cronjobs sem implantação.

Então, qual é a melhor abordagem aqui?

Tenha um bom dia,

Bastian

Eu escrevi um daemon que observa contêineres e agende trabalhos, definidos em seus metadados, neles. Isso chega mais perto de sua 1) solução. Exemplo:

version: '2'services:  wordpress:    image: wordpress  mysql:    image: mariadb    volumes:      - ./database_dumps:/dumps    labels:      deck-chores.dump.command: sh -c "mysqldump --all-databases > /dumps/dump-$$(date -Idate)"      deck-chores.dump.interval: daily

'Clássico', configuração cron-like também é possível.

Aqui estão os documento, aqui está o repositório de imagens.

O próprio Cron pode ser instalado e executado em primeiro plano (cron -f) tornando muito fácil de instalar em um recipiente. Para acessar outros contêineres, você provavelmente instalaria o docker no mesmo contêiner para a CLI do cliente (para não executar o daemon). Em seguida, para acessar o ambiente Docker do host, a solução mais comum é vincular a montagem do soquete docker (-v /var/run/docker.sock:/var/run/docker.sock). O único gotcha é que você precisa configurar o GID do docker dentro do contêiner para corresponder ao GID do host e, em seguida, adicionar usuários dentro do contêiner ao grupo do docker.

Isso significa que esses usuários têm o mesmo acesso de qualquer usuário do docker no host, por exemplo, acesso ao nível raiz, então você precisa confiar totalmente no usuário que os envia ou limitar os comandos que eles podem executar com algum tipo de equivalente sudo. A outra desvantagem é que isso é menos portátil, e os administradores com conhecimento de segurança provavelmente não aprovarão a execução de seus contêineres em seus sistemas.

O fallback da opção B é muito fácil com uma ferramenta como supervisord. Embora menos do que o "um processo por contêiner" ideal, também não é um anti-padrão, pois mantém todo o contêiner e as dependências juntas e remove quaisquer riscos de segurança para o host.

Se você vai com a primeira ou segunda opção se resume ao seu ambiente, quem está enviando os trabalhos, quantos contêineres precisam ter trabalhos enviados contra si mesmos, etc. Se for um administrador que envia trabalhos em muitos contêineres, um contêiner cron faz sentido. Mas se você é o desenvolvedor de aplicativos que precisa incluir um trabalho agendado com seu aplicativo como um pacote, vá para a segunda opção.

Execute cron em outro contêiner ou mesmo no host, mas execute o script via php-fpm (por exemplo . o cron iria "enrolar" ou algo o script PHP).

Certifique-se de proteger essa configuração com um token de segurança, limitações de rede, etc. Um aprimoramento pode ser ter um pool php-fpm separado com processos dinâmicos capazes de gerar no máximo um processo. Esta piscina só seria acessível pelo cron. Também pode se beneficiar de suas próprias configurações individuais, como um tempo de execução muito maior, mais ou menos memória, etc.

P. S.: você pode usar algo como presente para chamar o script diretamente no contêiner FPM e não passar pelo nginx.

Raciocínio: você provavelmente deseja acessar as mesmas bibliotecas, a mesma configuração etc. Executar um processo gerado aleatoriamente e não controlado por um gerenciador de sinais no Docker é uma péssima ideia.

Eu estava tentando conseguir algo semelhante.

Minha ideia inicial era iniciar trabalhos cron separados cron container e realmente executá-los dentro de outro contêiner (php) ou seja. ter crontab registro para cada docker run -i t $containerName $scriptName ... comando executando script diferente dentro do php recipiente

A abordagem não é realmente boa por causa das desvantagens @ BMitch mencionar. Também eu realmente não gosto de instalar docker para o recipiente.

Eu gostaria de oferecer outra solução adequada sob o seu #1 categoria: pode-se executar o php-fpm directamente. Embora não seja a solução mais elegante do mundo, oferece vantagens:

  1. Segurança - sem acesso especial ou privilegiado, basta usar host e porta (como php-host:9000) que já está aberto para nginx de dentro da rede virtual docker
  2. Apor cron gestão separada do php recipiente-portanto, o dimensionamento não é prejudicado
  3. Realmente usando cron para tarefas cronish - basta plantar o crontab e ser feito em vez de reimplementando o cron através de várias outras libs
  4. A execução do script não passa nginx, então ninguém pode executá-los diretamente via servidor web, você não precisa implementar nenhuma autenticação ou tais mecanismos
  5. Ainda menos problemas com permissões. Minha dockerização cron anterior estava tendo cron instalado dentro de outro php container e ter a base de código compartilhada usando volumes. Isso foi eficiente, mas as permissões tiveram que ser tratadas com cuidado como caches, DI, logs etc. tinha que ser acessível e gravável tanto pelo servidor web quanto por um cron usuario. Essa abordagem elimina o problema

A única desvantagem que encontrei até agora é que a primeira linha w/ hashbang (#!/usr/local/bin/php) é considerado como uma saída real e PHP Aviso sobre cabeçalhos já enviados é emitido (Cannot modify header information - headers already sent by ...)- deixar cair o hashbang corrige isso.

Como realmente fazer isso?

  1. Tenha um recipiente limpo, por exemplo alpine:3.7
  2. Instalar apk-cron e fcgi (informações do pacote)
  3. Execute algo como:
SCRIPT_FILENAME=/docroot/scripts/cron/example-script.php \REQUEST_METHOD=GET \cgi-fcgi -bind -connect php-fpm:9000

de dentro do crontab.

Mais informações sobre o tema: Conecte-se diretamente ao PHP-FPM

Eu fiz isso (com Docker compor mais ou menos automaticamente), mas como você iniciaria algum tipo de Cronjob baseado em PHP apenas com algum tipo de comando de rede? Se eu usar a porta 80, Tenho o tempo limite normal do PHP funcionando contra mim que não faz sentido… Não tenho certeza do que seria uma boa solução!

Não que eu entenda ou possa testar nada disso, mas há um exemplo nesse documento que diz que você pode executar um comando como este docker run --rm --name web2 --link db:DB training/webapp commandname, então se isso funcionar para você, execute cron em um contêiner e faça com que ele emita comandos como esse no(S) outro (s) contêiner (s).

#1! - Desculpa não saber. Não é o ponto de contêineres para que eles sejam “contidos”? Tipo,“seguro”? Eu não uso Docker ou contêineres de aplicativos, então não sei exatamente do que estou falando…

Você está totalmente certo de que eles devem ser “contidos”, mas você precisa ter alguns deles trabalhando juntos como uma peça de software. Se você não é capaz de executar seu software como um processo (e para ser honesto assim que você não é um profissional na escrita de seu próprio banco de dados a partir do zero você não é capaz de ) você precisa de alguns recipientes para trabalhar juntos. E eu não sei como executar Cronjobs com eles =/.

Comunicação entre contêineres (vinculação ou rede): Redirecting…