Week 11: Orchestrating containers


Tip
Wouldn’t it be cool if there was something to orchestrate this different services? Something that also gave us the capability to manage some logic between them?
A yaml file that:
depends_on), healthchecks, and scaling (e.g., docker compose up --scale).services is always needed, top level definition to introduce the docker servicesbuild specifies the folder from which the docker should be built upon. It will search for a Dockerfile in that folderdocker “turns” to docker composeTip
If no service is specified, we will refer to the whole compose file (all services)
docker compose up -> Start all services (foreground)docker compose up -d -> Start all services (detached)docker compose down -> Stop all servicesdocker compose ps -> List all running servicesdocker compose logs -> View logs from all servicesdocker compose exec api bash -> Open a bash terminal in the api serviceDocker allows us to scale services easily:
Note
We understand scaling as running multiple instances of the same service to handle increased load or provide redundancy.
For now, we’ve always built our images from a Dockerfile. What if we want to use an existing image from a registry and just configure it?
We can directly specify the image to use with the image key.
If our service has the mapping:
What’s the address we should use to see it from our browser?
localhost:4000Why localhost?
Localhost is a special address that always points to the machine you’re currently using. When you run a web server on your computer and map its port to your localhost, you’re essentially telling your computer to listen for incoming requests on that specific port.
If the server was running on a different machine, you would need to use that machine’s IP address or hostname to access it.
Can you detect the problem here?
Will we ever access the database from the outside?
No! The database is only needed by the backend service.
But what if…
No, you really shouldn’t expose the database to the outside world unless absolutely necessary.
In order to avoid exposing unnecessary ports, we can remove the ports section from the db service
But how does the backend service access the database then?
Docker Compose automatically creates a default network for all services defined in the docker-compose.yml file. Each service can communicate with other services using the service name as the hostname (IP).
So, in our case, the backend service can access the database using the hostname db and the default MySQL port 3306.
Using standalone Docker containers: 
Using Docker Compose: 
Sometimes, we want to make sure that a service starts only after another service is up and running We can use the depends_on key to specify these dependencies
Tip
Note that depends_on only ensures that the db service is started before the backend service. It does not guarantee that the db service is ready to accept connections. To ensure that a service is ready, you may need to implement health checks or wait-for-it scripts.
Sometimes, we want to persist data generated by a service, even if the container is removed. For example, a database service needs to store its data on disk.
We can use bind mounts to persist data
This will create a bind mount volume that maps the ./db-data directory on the host to the /var/lib/mysql directory in the container.
Tip
There’s something called named volumes as well, which are managed by Docker and not tied to a specific host directory, usually better for production environments. Feel free to check them out in the references!
build: for local Dockerfiles, image: to pull a registry image.host:container maps host ports; expose only what is necessary.docker compose build, up/down, ps, logs, exec; -d to detach, --scale to run multiple instances.depends_on to control startup order; consider health checks for readiness.depends_on guarantee that the depended-on service is ready to accept connections? If not, how to make it wait?image: is given without a tag (e.g., redis), what is pulled and why is that a reproducibility risk?docker compose up vs docker compose up -d?docker compose -d another alternative for?build: vs image: in a service definition?Create a super-simple api and implement a healthcheck endpoint.
Verify that the healthcheck works by using it in a depends_on clause in a docker-compose file.
Ready to have some fun? Check out the second part of the fourth AMSA activity here!

AMSA 2025-2026 - 🏠 Home