Can someone clarify the subtitles of docker compose?

I have a docker compose file which I think is nothing special or magical:

services:
  db:
    image: postgres:${POSTGRES_VERSION}
    hostname: ${COMPOSE_PROJECT_NAME}-db
    volumes:
      - type: volume
        source: db-data
        target: /var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: password

  web:
    build:
      context: .
      dockerfile: docker/Dockerfile

      # These come from the environment.  The shell scripts I'm using
      # source env.sh which define and export all of the Docker and
      # Compose variables.
      args:
        - COMPOSE_PROJECT_NAME
        - PORT
        - DOCKER_REPOSITORY
        - POSTGRES_VERSION
        - PROJECT_VERSION
        - RUBY_IMAGE
        - RUBY_VERSION
    hostname: ${COMPOSE_PROJECT_NAME}
    image: ${DOCKER_REPOSITORY}/${COMPOSE_PROJECT_NAME}:${PROJECT_VERSION}
    volumes:
      - .:/${COMPOSE_PROJECT_NAME}
    ports:
      - "${PORT}:${PORT}"
    depends_on:
      - db

volumes:
  db-data:
    external: true
    name: ${COMPOSE_PROJECT_NAME}-db

I think the right terminology is the web service is running in a container based on an image built from my Dockerfile. I do the docker compose build and the docker compose up. I use the services and eventually hit ^C to stop the web service which also kills the db service.

Now I do docker ps and there are nothing shown while docker ps -a shows the two containers with a Status of Exited. If I do docker compose up again, the same two containers (with the same container ids) are now Up.

Also, if I do docker exec -it hatred-web-1 zsh while the two containers are Up, I now have another process living inside the same container as the web service. All this is ok… I just wasn’t expecting a container that had Exited to be brought back to life.

And the other thing that, to me, is weird is that I can make local file changes inside the container, kill it, restart it, and those local file changes remain. If I rebuild the image with, for example, docker compose up --build, then the image is rebuilt and the local changes within the container are lost. I also get a new fresh container id.

Part of the reason for this post is to ask if all of the above is correct or are there subtle inaccuracies?

The real reason for this post is to ask if it is possible via the docker compose file to add another service (or perhaps it would have a different term) that is executing within the same container as the web service. I appear to be able to do this from the command line. Can I do it from within the compose file?

The other question is similar: how do I specify another service in the compose file that will use the same image as the web service? The web service builds the image. Once build, can I specify another service that uses the same image simply by duplicating the web service but omit the build section?

Indeed, it may be that I want / need to do this for a few other tasks that need to run at least using the same base image but would probably be better to run within the same container.

I know there is the general rule of one service per container but this is currently a development situation and so that rule seems a bit more restrictive than is practical.

Thank you for your help

Your observations are correct. Docker compose will re-use existing containers, unless the image is rebuild or the service configuration is modifed. It doesn’t matter if files inside the container filesystem are modified

You can not configure exec statements in the compose file. You might want to use a process supervions like s6-overlay in your image if you need to run more than one process in a container.

Yes, you can copy the definition of the web service using a different service name, excluding the build element, and it’s sub-elements. As long as the value for image: is identical, it will work.

Rule of thumb: application/services that use network communication to interact with other applications/services are usually better off in separate containers.

1 Like