Starting one container with Docker is manageable. Starting an application and its dependencies repeatedly—with the right ports, commands, and settings—is harder. Docker Compose stores those runtime settings in a docker-compose.yaml file and brings the containers up as a group. It is a simple way to test an application locally before deploying it to Kubernetes. section 2.3 section 2.3.2
Listing 2.16 Chapter02/2.3_Compose/docker-compose.yaml
services:
web:
build: ../timeserver #1
command: python3 server.py #2
ports: #3
- "8080:80" #3
A single-service file builds the web image from a local directory, runs the server, and maps host port 8080 to container port 80. From the file’s directory, run docker compose build and then docker compose up. The next run can reuse the settings instead of reconstructing a Docker command. section 2.3
For a faster editing loop, a bind mount can map the application folder on your computer to /app inside the container. The container then reads local files rather than the copies placed there when the image was built. This avoids a rebuild for file changes, but the running application must also reload changed code; the Python example adds a reloading library. Compiled applications may need a different development workflow, such as Skaffold. section 2.3.1
Listing 2.17 Chapter02/2.3.1_VolumeMount/docker-compose.yaml
services:
frontend:
build: .
command: python3 server.py
volumes: #1
- type: bind #1
source: . #1
target: /app #1
environment:
PYTHONDONTWRITEBYTECODE: 1 #2
ports:
- "8080:80"
#1 Binds the local container build directory into the container’s /app directory (matching the Dockerfile)
#2 Sets a new environment variable so that Python can be made to reload our source
The volume entry binds the current directory to /app. The file also records the server command, port mapping, and a Python environment setting, keeping the local run configuration together. section 2.3.1
Listing 2.20 Chapter02/2.3.2_MultipleServices/docker-compose.yaml
services:
frontend: #1
build: ../timeserver #1
command: python3 server.py #1
environment: #1
PYTHONDONTWRITEBYTECODE: 1 #1
ports: #1
- "8080:80" #1
db:
image: mysql:5.7 #2
volumes: #2
- db_data:/var/lib/mysql #2
restart: always #2
environment: #2
MYSQL_ROOT_PASSWORD: super secret password #2
MYSQL_DATABASE: my_database #2
MYSQL_USER: dev_user #2
MYSQL_PASSWORD: another secret password #2
volumes: #3
db_data: #3
A second service can use a published image instead of a local build: this example pairs a locally built frontend with mysql:5.7. It illustrates how to bring up a development dependency, although the demonstration frontend does not actually use the database. section 2.3.2
Compose is well suited to local development with a handful of services. Kubernetes is an option for local development too, especially when reproducing a production environment matters, and is better suited to more complex production deployment. Using Compose locally and Kubernetes in production means maintaining separate configurations, but the local file can omit production concerns such as replica counts and resource requirements. section 2.3.2 section 3.4














