Shell interativo usando o Docker Compose

271

Existe alguma maneira de iniciar um shell interativo em um contêiner usando apenas o Docker Compose? Eu tentei algo assim, no meu docker-compose.yml:

myapp:
  image: alpine:latest
  entrypoint: /bin/sh

Quando inicio este contêiner usando o docker-compose, ele sai imediatamente. Existem sinalizadores que eu possa adicionar ao comando do ponto de entrada ou como opção adicional ao myapp para iniciar como shell interativo?

Eu sei que existem opções de comando do docker nativo para conseguir isso, curioso para saber se é possível usar apenas o Docker Compose também.

drubb
fonte
Isso não deveria funcionar. Por exemplo, se você possui várias imagens com ponto de /bin/shentrada no seu arquivo de composição, o que deve fazer?
Xiongbing Jin
2
Hmh, por que não começar várias conchas? Por exemplo, um shell em um contêiner mysql para trabalhar com o mysql cli e um shell em um contêiner de backup para executar comandos de backup?
drubb
1
que tal docker-compose run myapp?
ivoba
1
@ibova O problema é docker-compose run myappque ele não expõe as portas. Então você tem que usar, docker-compose run --service-ports myappmas ainda não é muito conveniente.
The Fool
entrypoint: /bin/shdeve serentrypoint: "/bin/sh"
codentary

Respostas:

342

Você precisa incluir as seguintes linhas no seu docker-compose.yml:

version: "3"
services:
  app:
    image: app:1.2.3
    stdin_open: true # docker run -i
    tty: true        # docker run -t

O primeiro corresponde a -iin docker rune o segundo a -t.

Leon Carlo Valencia
fonte
3
esse stdin_opené o link que falta, por simplesmente fornecer o comportamento esperado quando eu me conecto a um dos meus contêineres que já está executando um shell.
Charney Kaye
9
@ TheFool, até eu tenho o mesmo problema. É melhor correrdocker-compose run <service_name>
Aswath K
4
Onde exatamente isso é adicionado? Dentro do serviço?
problemofficer
Essa parece ser a melhor resposta para a pergunta do OP. Como o problema é que o contêiner sai imediatamente, caso contrário, a utilização de um shell docker execnão funcionará.
RoyM 31/12/19
Isso me dá um erro no Windows:colorama\win32.py, line 152, in SetConsoleTitle: ctypes.ArgumentError: ‘ValueError’: embedded null character
cowlinator
210

A maneira canônica de obter um shell interativo com o docker-compose é usar: docker-compose run --rm myapp

Você pode definir stdin_open: true, tty: true, no entanto, que na verdade não fornecerá um shell adequado up, porque os logs estão sendo transmitidos por todos os contêineres.

Você também pode usar

docker exec -ti <container name> /bin/bash

para obter um shell em um contêiner em execução.

dnephin
fonte
16
Note que você precisa adicionar --service-portsse você expor as portas (ou seja, para um servidor web)
epelc
9
Atualizei minha resposta para fornecer mais informações e adicionar o --rmsinalizador para que o contêiner seja removido. A resposta de @ lynx0123 não está correta. Você não receberá um shell interativo se executar docker-compose up.
dnephin 1/09/16
2
Para que isso funcionasse usando o Docker para Windows, eu precisava do docker-compose v. 1.9.0 (consulte Problema no Github e PR ). A partir de 19/12/16, isso só é fornecido com versões beta do Docker for Windows. Então docker-compose runfunciona. Você também deseja adicionar command: /bin/bashao docker-compose.yml.
Joseph238
5
Essa deve ser a resposta principal. Era isso que eu procurava quando cheguei aqui.
Mkasberg
8
docker-compor up -d && docker attach <container_name>
Aaron McMillin
58

No exemplo oficial de introdução ( https://docs.docker.com/compose/gettingstarted/ ) com o seguinte docker-compose.yml:

version: '3'
services:
  web:
    build: .
    ports:
     - "5000:5000"
  redis:
    image: "redis:alpine"

Depois de iniciar isso docker-compose up, você pode facilmente desembolsar em seu rediscontêiner ou em seu webcontêiner com:

docker-compose exec redis sh
docker-compose exec web sh 
argila
fonte
44

docker-compose run myapp sh deve fazer o acordo.

Há alguma confusão com up/ run, mas os docker-compose rundocumentos têm ótimas explicações: https://docs.docker.com/compose/reference/run

Alex Povar
fonte
1
Muito obrigado. Apenas um pequeno complemento para esclarecer. docker-compose execute [nome-do-serviço-definido-em-docker-compose.yml] [sh ou bash].
theeranitp
23

Usando o docker-compose, achei a maneira mais fácil de fazer isso docker ps -a(depois de iniciar meus contêineres docker-compose up) e obter o ID do contêiner no qual quero ter um shell interativo (vamos chamá-lo de xyz123).

Então é uma questão simples de executar docker exec -ti xyz123 /bin/bash

e voila, uma concha interativa.

David Hersey
fonte
1
Não tenho certeza por que isso foi rejeitado - é uma ótima maneira de obter depuração, caso algo dê errado, e eu usei esse método com sucesso, tipo, dentro de um minuto depois de ler esta solução.
ericmjl
4
@ericmjl Porque é um processo de duas etapas, onde a pergunta especificamente sobre o uso de recursos Docker-compor, e já foi afirmado na outra resposta
OneCricketeer
19

Se alguém do futuro também estiver aqui:

docker-compose exec container_name sh

ou

docker-compose exec container_name bash

ou você pode executar linhas únicas como

docker-compose exec container_name php -v

Isso é depois que você já tem seus contêineres em funcionamento

Eleonora Ivanova
fonte
2

Você pode fazer docker-compose exec SERVICE_NAME shna linha de comando. O SERVICE_NAMEé definido no seu docker-compose.yml. Por exemplo,

services:
    zookeeper:
        image: wurstmeister/zookeeper
        ports:
          - "2181:2181"

O SERVICE_NAMEseria "tratador".

Yu N.
fonte
2

Essa pergunta é muito interessante para mim porque tenho problemas, quando executo o contêiner após a execução terminar imediatamente sair e corrigi com -it:

docker run -it -p 3000:3000 -v /app/node_modules -v $(pwd):/app <your_container_id>

E quando devo automatizá-lo com o docker compor:

version: '3'
services:
    frontend:
        stdin_open: true
        tty: true
        build: 
            context: .
            dockerfile: Dockerfile.dev
        ports: 
            - "3000:3000"
        volumes: 
            - /app/node_modules
            - .:/app

Isso torna o truque: stdin_open: true, tty: true

Este é um projeto gerado com o create-react-app

Dockerfile.dev parece isso que:

FROM node:alpine

WORKDIR '/app'

COPY package.json .
RUN npm install

COPY . . 

CMD ["npm", "run", "start"]

Espero que este exemplo ajude outros a executar um front-end (reagir por exemplo) no contêiner do docker.

Carnaru Valentin
fonte
0

Se ymlfor chamado docker-compose.yml, pode ser iniciado com um simples $ docker-compose up. A conexão correspondente de um terminal pode ser simples (considere que o ymlserviço especificado foi chamado myservice):

$ docker-compose exec myservice sh

No entanto, se você estiver usando um ymlnome de arquivo diferente , como docker-compose-mycompose.yml, ele deve ser iniciado usando $ docker-compose -f docker-compose-mycompose.yml up. Para conectar um terminal interativo, você deve especificar o ymlarquivo também, como:

$ docker-compose -f docker-compose-mycompose.yml exec myservice sh
Cleber Jorge Amaral
fonte