🎼Big Compose update

This commit is contained in:
Jerome Petazzoni
2021-04-26 01:45:29 +02:00
parent 56b9b864bb
commit 58ccebf5c7

View File

@@ -1,51 +1,40 @@
# Compose for development stacks
Dockerfiles are great to build container images.
Dockerfile = great to build *one* container image.
But what if we work with a complex stack made of multiple containers?
What if we have multiple containers?
Eventually, we will want to write some custom scripts and automation to build, run, and connect
our containers together.
What if some of them require particular `docker run` parameters?
There is a better way: using Docker Compose.
How do we connect them all together?
In this section, you will use Compose to bootstrap a development environment.
... Compose solves these use-cases (and a few more).
---
## What is Docker Compose?
## Life before Compose
Docker Compose (formerly known as `fig`) is an external tool.
Before we had Compose, we would typically write custom scripts to:
Unlike the Docker Engine, it is written in Python. It's open source as well.
- build container images,
The general idea of Compose is to enable a very simple, powerful onboarding workflow:
- run containers using these images,
1. Checkout your code.
- connect the containers together,
- rebuild, restart, update these images and containers.
---
## Life with Compose
Compose enables a simple, powerful onboarding workflow:
1. Checkout our code.
2. Run `docker-compose up`.
3. Your app is up and running!
---
## Compose overview
This is how you work with Compose:
* You describe a set (or stack) of containers in a YAML file called `docker-compose.yml`.
* You run `docker-compose up`.
* Compose automatically pulls images, builds containers, and starts them.
* Compose can set up links, volumes, and other Docker options for you.
* Compose can run the containers in the background, or in the foreground.
* When containers are running in the foreground, their aggregated output is shown.
Before diving in, let's see a small example of Compose in action.
3. Our app is up and running!
---
@@ -55,20 +44,61 @@ class: pic
---
## Checking if Compose is installed
## Life after Compose
If you are using the official training virtual machines, Compose has been
pre-installed.
(Or: when do we need something else?)
If you are using Docker for Mac/Windows or the Docker Toolbox, Compose comes with them.
- Compose is *not* an orchestrator
If you are on Linux (desktop or server environment), you will need to install Compose from its [release page](https://github.com/docker/compose/releases) or with `pip install docker-compose`.
- It isn't designed to need to run containers on multiple nodes
You can always check that it is installed by running:
(it can, however, work with Docker Swarm Mode)
```bash
$ docker-compose --version
```
- Compose isn't ideal if we want to run containers on Kubernetes
- it uses different concepts (Compose services ≠ Kubernetes services)
- it needs a Docker Engine (althought containerd support might be coming)
---
## First rodeo with Compose
1. Write Dockerfiles
2. Describe our stack of containers in a YAML file called `docker-compose.yml`
3. `docker-compose up` (or `docker-compose up -d` to run in the background)
4. Compose pulls and builds the required images, and starts the containers
5. Compose shows the combined logs of all the containers
(if running in the background, use `docker-compose logs`)
6. Hit Ctrl-C to stop the whole stack
(if running in the background, use `docker-compose stop`)
---
## Iterating
After making changes to our source code, we can:
1. `docker-compose build` to rebuild container images
2. `docker-compose up` to restart the stack with the new images
We can also combine both with `docker-compose up --build`
Compose will be smart, and only recreate the containers that have changed.
When working with interpreted languages:
- dont' rebuild each time
- leverage a `volumes` section instead
---
@@ -77,38 +107,37 @@ $ docker-compose --version
First step: clone the source code for the app we will be working on.
```bash
$ cd
$ git clone https://github.com/jpetazzo/trainingwheels
...
$ cd trainingwheels
git clone https://github.com/jpetazzo/trainingwheels
cd trainingwheels
```
Second step: start your app.
Second step: start the app.
```bash
$ docker-compose up
docker-compose up
```
Watch Compose build and run your app with the correct parameters,
including linking the relevant containers together.
Watch Compose build and run the app.
That Compose stack exposes a web server on port 8000; try connecting to it.
---
## Launching Our First Stack with Compose
Verify that the app is running at `http://<yourHostIP>:8000`.
We should see a web page like this:
![composeapp](images/composeapp.png)
Each time we reload, the counter should increase.
---
## Stopping the app
When you hit `^C`, Compose tries to gracefully terminate all of the containers.
When we hit Ctrl-C, Compose tries to gracefully terminate all of the containers.
After ten seconds (or if you press `^C` again) it will forcibly kill
them.
After ten seconds (or if we press `^C` again) it will forcibly kill them.
---
@@ -118,13 +147,13 @@ Here is the file used in the demo:
.small[
```yaml
version: "2"
version: "3"
services:
www:
build: www
ports:
- 8000:5000
- ${PORT-8000}:5000
user: nobody
environment:
DEBUG: 1
@@ -143,9 +172,9 @@ services:
A Compose file has multiple sections:
* `version` is mandatory. (We should use `"2"` or later; version 1 is deprecated.)
* `version` is mandatory. (Typically use "3".)
* `services` is mandatory. A service is one or more replicas of the same image running as containers.
* `services` is mandatory. Each service corresponds to a container.
* `networks` is optional and indicates to which networks containers should be connected.
<br/>(By default, containers will be connected on a private, per-compose-file network.)
@@ -164,6 +193,8 @@ A Compose file has multiple sections:
* Version 3 added support for deployment options (scaling, rolling updates, etc).
* Typically use `version: "3"`.
The [Docker documentation](https://docs.docker.com/compose/compose-file/)
has excellent information about the Compose file format if you need to know more about versions.
@@ -201,34 +232,45 @@ For the full list, check: https://docs.docker.com/compose/compose-file/
---
## Compose commands
## Environment variables
We already saw `docker-compose up`, but another one is `docker-compose build`.
- We can use environment variables in Compose files
It will execute `docker build` for all containers mentioning a `build` path.
(like `$THIS` or `${THAT}`)
It can also be invoked automatically when starting the application:
- We can provide default values, e.g. `${PORT-8000}`
```bash
docker-compose up --build
```
- Compose will also automatically load the environment file `.env`
Another common option is to start containers in the background:
(it should contain `VAR=value`, one per line)
```bash
docker-compose up -d
```
- This is a great way to customize build and run parameters
(base image versions to use, build and run secrets, port numbers...)
---
## Check container status
## Running multiple copies of a stack
It can be tedious to check the status of your containers with `docker ps`,
especially when running multiple apps at the same time.
- Copy the stack in two different directories, e.g. `front` and `frontcopy`
Compose makes it easier; with `docker-compose ps` you will see only the status of the
containers of the current stack:
- Compose prefixes images and containers with the directory name:
`front_www`, `front_www_1`, `front_db_1`
`frontcopy_www`, `frontcopy_www_1`, `frontcopy_db_1`
- Alternatively, use `docker-compose -p frontcopy`
(to set the `--project-name` of a stack, which default to the dir name)
- Each copy is isolated from the others (runs on a different network)
---
## Checking stack status
We have `ps`, `docker ps`, and similarly, `docker-compose ps`:
```bash
$ docker-compose ps
@@ -238,6 +280,10 @@ trainingwheels_redis_1 /entrypoint.sh red Up 6379/tcp
trainingwheels_www_1 python counter.py Up 0.0.0.0:8000->5000/tcp
```
Shows the status of all the containers of our stack.
Doesn't show the other containers.
---
## Cleaning up (1)
@@ -281,47 +327,39 @@ Use `docker-compose down -v` to remove everything including volumes.
## Special handling of volumes
Compose is smart. If your container uses volumes, when you restart your
application, Compose will create a new container, but carefully re-use
the volumes it was using previously.
- When an image gets updated, Compose automatically creates a new container
This makes it easy to upgrade a stateful service, by pulling its
new image and just restarting your stack with Compose.
- The data in the old container is lost...
- ... Except if the container is using a *volume*
- Compose will then re-attach that volume to the new container
(and data is then retained across database upgrades)
- All good database images use volumes
(e.g. all official images)
---
## Compose project name
class: extra-details
* When you run a Compose command, Compose infers the "project name" of your app.
## A bit of history and trivia
* By default, the "project name" is the name of the current directory.
- Compose was initially named "Fig"
* For instance, if you are in `/home/zelda/src/ocarina`, the project name is `ocarina`.
- Compose is one of the only components of Docker written in Python
* All resources created by Compose are tagged with this project name.
(almost everything else is in Go)
* The project name also appears as a prefix of the names of the resources.
- In 2020, Docker introduced "Compose CLI":
E.g. in the previous example, service `www` will create a container `ocarina_www_1`.
- `docker compose` command to deploy Compose stacks to some clouds
* The project name can be overridden with `docker-compose -p`.
- progressively getting feature parity with `docker-compose`
---
## Running two copies of the same app
If you want to run two copies of the same app simultaneously, all you have to do is to
make sure that each copy has a different project name.
You can:
* copy your code in a directory with a different name
* start each copy with `docker-compose -p myprojname up`
Each copy will run in a different network, totally isolated from the other.
This is ideal to debug regressions, do side-by-side comparisons, etc.
- also provides numerous improvements (e.g. leverages BuildKit by default)
???