ChatGPT解决这个技术问题 Extra ChatGPT

Interactive shell using Docker Compose

Is there any way to start an interactive shell in a container using Docker Compose only? I've tried something like this, in my docker-compose.yml:

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

When I start this container using docker-compose up it's exited immediately. Are there any flags I can add to the entrypoint command, or as an additional option to myapp, to start an interactive shell?

I know there are native docker command options to achieve this, just curious if it's possible using only Docker Compose, too.

This is not supposed to work. For example, if you have multiple images with /bin/sh entrypoint in your compose file, what should it do?
Hmh, why not just start multiple shells? For example, a shell into a mysql container to work with mysql cli, and a shell into a backup container to run backup commands?
what about docker-compose run myapp ?
@ibova The problem is with docker-compose run myapp is that it won't expose the ports. So you have to use docker-compose run --service-ports myapp but still its not very convenient.
@codentary It is just YAML, so quotes are optional in this particular case.

C
Cellcore

You need to include the following lines in your docker-compose.yml:

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

The first corresponds to -i in docker run and the second to -t.


that stdin_open is the missing link, for simply providing me the expected behavior when I attach to one of my containers that is already running a shell.
@TheFool, Even I got the same issue. Its better to run docker-compose run <service_name>
Where exactly is this added? Inside the service?
This seems to be the best answer to the OP's question.. since the issue is that the container exits immediately otherwise, so getting a shell using docker exec on it is not going to work.
This still does not work if I use docker-compose up and entrypoint ["/bin/sh"]. Although the container does not exist immediately. Is the input attached to the entrypoint?
q
questionto42standswithUkraine

The canonical way to get an interactive shell with docker-compose is to use:

docker-compose run --rm myapp

(With the service name myapp taken from your example. More general: it must be an existing service name in your docker-compose file, myapp is not just a command of your choice. Example: bash instead of myapp would not work here.)

You can set stdin_open: true, tty: true, however that won't actually give you a proper shell with up, because logs are being streamed from all the containers.

You can also use

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

to get a shell on a running container.


Note you need to add --service-ports if you expose any ports(ie for a web server)
I've updated my answer to provide more information and add the --rm flag so that the container is removed. The answer by @lynx0123 is not correct. You will not get an interactive shell if you run docker-compose up.
To get this to work using Docker for Windows, I needed docker-compose v. 1.9.0 (see Github issue and PR). As of 12/19/16, this only ships with beta versions of Docker for Windows. Then docker-compose run works. You'll also want to add command: /bin/bash to docker-compose.yml.
This should be the top answer. This is what I was looking for when I came here.
docker-compose up -d && docker attach
c
clay

The official getting started example (https://docs.docker.com/compose/gettingstarted/) uses the following docker-compose.yml:

version: "3.9"
services:
  web:
    build: .
    ports:
      - "8000:5000"
  redis:
    image: "redis:alpine"

After you start this with docker-compose up, you can shell into either your redis container or your web container with:

docker-compose exec redis sh
docker-compose exec web sh 

And why with other images I can't do it, I just asked here stackoverflow.com/questions/66638731/…
A
Alex Povar

docker-compose run myapp sh should do the deal.

There is some confusion with up/run, but docker-compose run docs have great explanation: https://docs.docker.com/compose/reference/run


Thank you so much. Just a little add to clarify. docker-compose run [your-service-name-defined-in-docker-compose.yml] [sh or bash].
I think this is the most straightforward of answers. I needed to verify the environment is correct for the service by going docker-compose run <service-name> sh as suggested.
To override the entrypoint configured in docker-compose.yml I had to use: docker-compose run --entrypoint /bin/bash myapp
This really did the trick, when working with docker-compose!!
r
rmcsharry

If anyone from the future also wanders up here:

docker-compose exec service_name sh

or

docker-compose exec service_name bash

or you can run single lines like

docker-compose exec service_name php -v

That is after you already have your containers up and running.

The service_name is defined in your docker-compose.yml file


This is incorrect it is: docker-compose exec <service_name>, not docker-compose exec <container_name>.
And why with other images I can't do it, I just asked here stackoverflow.com/questions/66638731/…
D
David Hersey

Using docker-compose, I found the easiest way to do this is to do a docker ps -a (after starting my containers with docker-compose up) and get the ID of the container I want to have an interactive shell in (let's call it xyz123).

Then it's a simple matter to execute docker exec -ti xyz123 /bin/bash

and voila, an interactive shell.


Not sure why this was down-voted - it's a great way to get debugging in case anything goes wrong, and I used this method with success, like, within a minute of reading this solution.
@ericmjl Because it's a two step process where the question asked specifically about using docker-compose features, and was already stated in the other answer
C
Carnaru Valentin

This question is very interesting for me because I have problems, when I run container after execution finishes immediately exit and I fixed with -it:

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

And when I must automate it with docker compose:

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

This makes the trick: stdin_open: true, tty: true

This is a project generated with create-react-app

Dockerfile.dev it looks this that:

FROM node:alpine

WORKDIR '/app'

COPY package.json .
RUN npm install

COPY . . 

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

Hope this example will help other to run a frontend(react in example) into docker container.


Hey @Carnaru can you tell me the reason of using "- /app/node_modules" command under the volume section
@aashirkhan it's related to using volumes and having the container use the node_modules in the container rather than your local files
C
Cleber Jorge Amaral

If the yml is called docker-compose.yml it can be launched with a simple $ docker-compose up. The corresponding attachment of a terminal can be simply (consider that the yml has specified a service called myservice):

$ docker-compose exec myservice sh

However, if you are using a different yml file name, such as docker-compose-mycompose.yml, it should be launched using $ docker-compose -f docker-compose-mycompose.yml up. To attach an interactive terminal you have to specify the yml file too, just like:

$ docker-compose -f docker-compose-mycompose.yml exec myservice sh


P
Paul Roub

I prefer

docker-compose exec my_container_name bash

M
Maik Lowrey

A addition to this old question, as I only had the case last time. The difference between sh and bash. So it can happen that for some bash doesn't work and only sh does.

So you can: docker-compose exec CONTAINER_NAME sh

and in most cases: docker-compose exec CONTAINER_NAME bash

use.

If you have time. The difference between sh and bash is well explained here: https://www.baeldung.com/linux/sh-vs-bash


J
J. Scott Elblein

You can do docker-compose exec SERVICE_NAME sh on the command line. The SERVICE_NAME is defined in your docker-compose.yml. For example,

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

The SERVICE_NAME would be "zookeeper".


M
MrBB

According to documentation -> https://docs.docker.com/compose/reference/run/

You can use this docker-compose run --rm app bash

[app] is the name of your service in docker-compose.yml