Docker Compose mantém o contêiner em execução

101

Quero iniciar um serviço com docker-compose e manter o contêiner em execução para que possa obter seu endereço IP por meio de 'docker inspect'. No entanto, o contêiner sempre sai logo após a inicialização.

Tentei adicionar "command: [" sleep "," 60 "]" e outras coisas ao docker-compose.yml, mas sempre que adiciono a linha com "command: ..." não consigo chamar "docker-compose up" pois receberei a mensagem "Não é possível iniciar o contêiner ..... Erro de sistema: caractere inválido 'k' procurando o início do valor"

Eu também tentei adicionar "CMD sleep 60" e outros enfeites ao próprio Dockerfile, mas esses comandos não parecem ser executados.

Existe uma maneira fácil de manter o contêiner vivo ou de consertar um dos meus problemas?

EDIT: Aqui está o arquivo Compose que desejo executar:

version: '2'
services:
  my-test:
    image: ubuntu
    command: bash -c "while true; do echo hello; sleep 2; done"

Está funcionando bem Se eu começar com docker-compose no OS X, mas se eu tentar o mesmo no Ubuntu 16.04, aparece a mensagem de erro acima.

Se eu tentar a abordagem com o Dockerfile, o Dockerfile ficará assim:

FROM ubuntu:latest
CMD ["sleep", "60"]

Que parece não fazer nada

EDIT 2: Tenho que me corrigir, descobri que era o mesmo problema com o Dockerfile e o docker-compose.yml: Cada vez que adiciono "CMD ..." ao Dockerfile OU adiciono "command ..." o arquivo de composição, recebo o erro acima com o caractere inválido. Se eu remover os dois comandos, ele funcionará perfeitamente.

dingoglotz
fonte
1
Inclua docker-compose.yml, Dockerfile e todos os scripts que você está tentando depurar.
BMitch
Uma discussão relacionada, para os interessados: Fluxo de trabalho de desenvolvimento para servidor e cliente usando Docker Compose?
blong

Respostas:

128

Para manter um contêiner em execução ao iniciá-lo docker-compose, use o seguinte comando

command: tail -F anything

Então, seu docker-compose.yml se torna

version: '2'
services:
  my-test:
    image: ubuntu
    command: tail -F anything

e você pode executar um shell para entrar no contêiner usando o seguinte comando

docker exec -i -t composename_my-test_1 bash

onde composenameé o nome que docker-composeprecede seus contêineres.

Nick Settje
fonte
1
Como você para o contêiner quando terminar de usá-lo? Existe um tipo de comando Ctrl + C, Ctrl + Z? No momento, preciso fechar o terminal para sair.
mac10688 de
Se você estiver dentro do contêiner, poderá digitar exitpara voltar à máquina host. Se você estiver em seu host, poderá interromper o contêiner usando Docker ( docker stop composename_my-test_1) ou Docker Compose ( docker-compose stop).
Nick Settje
2
@ Alexis.Rolland Se você estiver disposto a fazer uma nova pergunta do SO e compartilhar mais alguns detalhes, ficaria mais do que feliz em dar uma olhada. Meu palpite é que seu erro tem algo a ver com os internos de um de seus contêineres, em oposição a um problema com o Docker ou seu sistema operacional host.
Nick Settje
1
@ mac10688 se não houver prompt na sessão do contêiner anexado, tente ctrl-d para desanexar
Stark
7
/dev/nullseria melhor no lugar para o anythingcomando ref. stackoverflow.com/a/48732671/248616
Nam G VU
90

Você pode usar a ttyopção de configuração.

version: '3'

services:
  app:
    image: node:8
    tty: true           # <-- This option

Nota: Se você usar Dockerfile para imagem e CMDno Dockerfile, esta opção não funcionará; no entanto, você pode usar a entrypointopção no arquivo de composição que limpa o CMDdo Dockerfile.

pulo alto
fonte
9
Isso funciona, e parece menos hacky do que tail -f /dev/null. Com isso, posso executar um ambiente de desenvolvimento em contêiner com um banco de dados postgres anexado docker-compose upe executar um shell por meio de outro terminal usando docker exec.
Psiloc
1
Embora atualmente NÃO esteja bem documentado. Esta é uma opção oficial que terá o mesmo efeito que tail -f /dev/nullou tail -f anything, veja aqui: docs.docker.com/compose/compose-file
b01
2
@ABMRuman & Psiloc, funciona apenas quando você não usa "command" no arquivo docker-compose.yml. Ao usar o "comando" você precisa de outro hack - portanto, o hack tail -F é perfeitamente adequado aqui.
asafel
1
Esta deve ser a melhor resposta se você usar o entrypoint no dockerfile.
DDKV587
54

Com base no comentário de @aanand no GitHub em 26 de agosto de 2015 , pode-se usar tail -f /dev/nullno docker-compose para manter o contêiner em execução.

exemplo docker-compose.yml

version: '3'
services:
  some-app:
    command: tail -f /dev/null

Por que este comando?

A única razão para escolher essa opção foi que ela recebeu muitos polegares para cima no GitHub, mas a resposta com maior votação não significa que seja a melhor resposta. O segundo motivo foi pragmático, pois os problemas tiveram que ser resolvidos o mais rápido possível devido aos prazos.

030
fonte
2
porque exatamente este comando? O que o torna melhor do que outros? No meu caso, apenas começar uma festa também
funcionou
@ N4ppeL Boa pergunta. A única razão pela qual escolhi essa opção foi porque ela recebeu muitos polegares para cima no github, mas a resposta com maior votação não significa que seja a melhor resposta. O segundo motivo foi pragmático, pois tinha que resolver o problema o mais rápido possível devido aos prazos.
030
17
  • Crie um arquivo chamado docker-compose.yml
  • Adicione o seguinte ao arquivo
version: "3"

services:
  ubuntu:
    image: ubuntu:latest
    tty: true
  • Permanecendo no mesmo diretório, execute a docker-compose up -dpartir do terminal
  • Execute docker pspara obter o nome ou id do contêiner
  • Você pode correr docker inspect $container_id
  • Você pode entrar no contêiner e obter um shell bash em execução docker-compose exec ubuntu /bin/bashoudocker-compose exec ubuntu /bin/sh
  • Quando terminar, certifique-se de estar fora do contêiner e execute docker-compose down

Aqui está um pequeno script bash ( my-docker-shell.sh) para criar o arquivo docker compose, executar o contêiner, fazer login no contêiner e, finalmente, limpar o contêiner docker e o arquivo docker compose quando você fizer logout.

#!/bin/bash

cat << 'EOF' > ./docker-compose.yml
---

version: "3"

services:
  ubuntu:
    image: ubuntu:latest
    command: /bin/bash
    # tty: true

...
EOF

printf "Now entering the container...\n"
docker-compose run ubuntu bash
docker-compose down

rm -v ./docker-compose.yml
GMaster
fonte
1
Embora essa não seja uma resposta real à pergunta, achei extremamente valiosa! Fui além para usar funções bashrc globais para esta abordagem: gist.github.com/loopmode/4d59a4e9a0a2ffacaec2dd14db4ae8bd
loopmode
8

No Dockerfile, você pode usar o comando:

{CMD sleep infinity}
John
fonte
2

Como o comentador afirmou, teríamos que ver o Dockerfile em questão para lhe dar uma resposta completa, mas esse é um erro muito comum. Posso garantir que o comando que você está tentando executar está iniciando um processo em segundo plano. Este pode ser o comando que você executaria em situações não Docker, mas é a coisa errada a se fazer em um Dockerfile. Por exemplo, se o que você está executando normalmente é definido como um serviço do sistema, você pode usar algo como "systemctl start". Isso iniciaria o processo em segundo plano, o que não funcionaria. Você tem que executar o processo em primeiro plano, então todo o processo será bloqueado.

David M. Karr
fonte
0

Apenas uma nota rápida

Eu testei uma imagem única com base em golang, então quando eu chamo docker-compose downaqui o que eu obtenho:

version: "3.1"
...
command: tail -f /dev/null   # stopping container takes about 10 sec.
tty: true                    # stopping container takes about 2 sec.

Informações do meu sistema:

Ubuntu 18.04.4 LTS (64-bit)
Docker version 19.03.6, build 369ce74a3c
docker-compose version 1.26.0, build d4451659
Smokehill
fonte
-3

Ok, encontrei meu erro. No Dockerfile da imagem usada para compor, especifiquei que a imagem base deveria ser ubuntu: latest, mas anteriormente criei uma imagem chamada ubuntu por mim e essa imagem não funcionou. Então, eu não usei a imagem original do ubuntu, mas sim uma versão corrompida da minha própria imagem também chamada de ubuntu.

dingoglotz
fonte