16

I've been looking for the answer for a while, but I haven't found it and I need to understand before I go ahead with my tests.

I am creating an image based on Alpine by installing bash as in the following image:

FROM alpine:3.12

RUN apk add --no-cache --upgrade bash rsync gzip \
&& rm -rf /var/cache/apk/*

COPY ./docker/backup/hello.sh /hello.sh

RUN mkdir /backup \
&& chmod u+x /hello.sh

WORKDIR /backup

ENTRYPOINT ["sh","/hello.sh"]
CMD ["/bin/bash"]

hello.sh

#!/bin/sh
echo "=> Hello Word"
echo "$@"
exec "$@"

The first time I tried bash I could not access with the following command:

docker-compose exec myalpine bash

But searching if I found the answer, I had to put in my docker-compose.yml tty: true, and I already was able to access the myalpine container shell after launching the command docker-compose up -d

Resulting in a part of my docker-compose.yml as follows

services:
  myalpine:
    build:
      context: ./
      dockerfile: ./docker/backup/Dockerfile
      args:
        - DOCKER_ENV=${DOCKER_ENV}
    restart: unless-stopped
    tty: true
    container_name: ${PROJECT_NAME}-files
    volumes:
      - appdata:/app
      - ./data/app/backup:/backup
  mysql:
    build:
      context: ./
      dockerfile: ./docker/mysql/Dockerfile
      args:
        - MYSQL_VERSION=${MYSQL_VERSION}
        - DOCKER_ENV=${DOCKER_ENV}
    restart: always
    container_name: ${PROJECT_NAME}-mysql
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    volumes:
      - dbdata:/var/lib/mysql
    networks:
      - db

And now my question is why in other services of my docker-compose like mysql, I can access the bash without adding tty:true?

Example:

docker-compose exec mysql bash

I can access without having added tty:true to the docker-compose.yml, so there must be something in Alpine's image that I don't understand and would like to understand.

jcarlosweb
  • 846
  • 1
  • 14
  • 30

1 Answers1

15

I had reproduced your example with a cut-down version of the dockerfile and the docker-compose.yaml, and after running docker-compose up. First I ran without a tty attached, so I have the following:

~$ docker-compose up
...
...
WARNING: Image for service myalpine was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating test-fies ... done
Attaching to test-fies
test-fies   | => Hello Word
test-fies   | /bin/bash

~# docker ps
CONTAINER ID   IMAGE             COMMAND                  CREATED         STATUS                                  PORTS                                              NAMES
9a72817b0e28   tty_up_myalpine   "sh /hello.sh /bin/b…"   5 minutes ago   Restarting (0) Less than a second ago                                                      myalpine-fies

As you can see, the container is restarting all the time. Reason for this is that the hello.sh as an entrypoint will receive the command /bin/bash and will execute the bash. This will try to create an interactive shell but since there is no tty the creation of the shell fails and the container is stopped. Because the container is marked restart: unless-stopped it will be in a constant loop of restarting.

Since the container is not running, you are not able to execute docker-compose exec myalpine bash

Once you add a tty to the container, bash will be able to create interactive session and the container will be started.

CONTAINER ID   IMAGE             COMMAND                  CREATED          STATUS         PORTS                                              NAMES
745f5139f510   tty_up_myalpine   "sh /hello.sh /bin/b…"   10 seconds ago   Up 9 seconds                                                      myalpine-fies

Reason why this is not a case with mysql is that this image ends up initiating a daemon process which is a non-interactive process that is detached from a tty.

jordanvrtanoski
  • 5,104
  • 1
  • 20
  • 29
  • 3
    Perfect, one more thing; is there any way to simulate a daemon to not add tty? I think that way the doubt will be clearer. – jcarlosweb Mar 15 '21 at 15:57
  • 2
    daemons are usually written in compiled languages like `C/C++`, but for a proof of concept, you can simulate one by changing the dockerfile's `CMD` line to `CMD ["/bin/bash","-c", "trap \"\" INT; while [ true ]; do sleep 1; done;"]` – jordanvrtanoski Mar 15 '21 at 16:38
  • 1
    @jcarlosweb I had success with using `bash -i` as the last command of my entrypoint script (or `command`), then I can do `docker-compose run ` and get a shell in the container. (doesn't even require `bash` at the end of the run command, nor setting the `tty:` or `stdin_open:` to `true` ... (When troubleshooting/working in a container/service that's not running a daemon, for whatever reason) – Aaron Wallentine Dec 24 '21 at 04:27