drubb
drubb

Reputation: 15781

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.

Upvotes: 651

Views: 744340

Answers (14)

dnephin
dnephin

Reputation: 28040

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. For 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.

Upvotes: 481

Leon Carlo Valencia
Leon Carlo Valencia

Reputation: 8737

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.

Upvotes: 823

Cleber Jorge Amaral
Cleber Jorge Amaral

Reputation: 1442

You can get an interactive shell with docker-compose using the following command (considering that the yml has specified a service called myservice):

$ docker-compose exec myservice sh

In the case of using a different yml file name, such as docker-compose-mycompose.yml, to get the interactive terminal, it is necessary to specify the yml, like:

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

Upvotes: 13

aknott
aknott

Reputation: 219

You can execute the shell through docker compose run.

compose.yml:

services:
  myapp:
    build: .

Dockerfile

FROM alpine:latest

Commandline on host

docker compose run --rm myapp sh -c "/bin/sh"

You might also want to mount some volumes in the compose file to persist whatever you are doing inside the container in compose.yml:

services:
  myapp:
    build: .
    volumes:
      - .:/app

I have mounted the current directory on host to the directory /app inside the container.

Upvotes: 1

IK Cheng
IK Cheng

Reputation: 41

I found the following steps can open an interactive shell, although it's not directly with docker-compose:

  • After running docker-compose up
  • Check the name of the container using docker ps -a
  • Choose the container name you want to open an interactive bash shell for
  • Run docker exec -it containerName bash

Your terminal should now be in the bash shell of the container and you can interact with its content.

Hope this helps.

Upvotes: 1

clay
clay

Reputation: 20370

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 

Upvotes: 148

Eleonora Ivanova
Eleonora Ivanova

Reputation: 813

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

Upvotes: 72

Maik Lowrey
Maik Lowrey

Reputation: 17546

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

Upvotes: 5

MisterLexisDev
MisterLexisDev

Reputation: 140

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

Upvotes: 2

alec vinent
alec vinent

Reputation: 99

I prefer

docker-compose exec my_container_name bash

Upvotes: 9

Carnaru Valentin
Carnaru Valentin

Reputation: 1846

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.

Upvotes: 11

Yu N.
Yu N.

Reputation: 2293

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".

Upvotes: 4

Alex Povar
Alex Povar

Reputation: 4960

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

Upvotes: 93

David Hersey
David Hersey

Reputation: 1049

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.

Upvotes: 38

Related Questions