Interactive Shell Using Docker Compose

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.

6

12 Answers

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.

7

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.

9

The official getting started example () 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 
1

docker-compose run myapp sh should do the deal.

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

4

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

2

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.

2

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.

2

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

I prefer

docker-compose exec my_container_name bash

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:

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

According to documentation ->

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

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Maya Lin-Takahashi
Author

Maya Lin-Takahashi

Maya is a hardware enthusiast who tests and reviews smart home devices, smartphones, wearables, and audio gear. She focuses on practical consumer value and build quality.