Build an Application with Docker Compose¶
This lab will take you through unifying the container work you’ve done so far in the class to build a modern application with multiple components.
Introduction¶
It take many containers to build a real application. Up until now we’ve deployed containers one at a time. That’s tedious, accident prone and time consuming. There’s a better way using Docker Compose. This lab will guide you through making a complex application.
Step 1: Install Docker Compose¶
On recent Ubuntu systems like the ones we’re using you can install the docker-compose
command using apt
:
$ apt-install docker-compose
Easy!
Step 2: Gather All Your Containers in One Place¶
In the course we’ve built the following containers over the weeks:
Apache (we’ll use this for serving static files)
DNS
HelloApp (the simple app server we created)
Let’s put them into a single directory structure so we can build them as a group. The directory should look like this:
$ tree
.
├── Apache
│ └── html
│ └── index.html
├── DNS
│ ├── db.mike.cis.cabrillo.edu
│ ├── db.mike-ipv4
│ ├── db.mike-ipv6
│ ├── Dockerfile
│ ├── entrypoint.sh
│ └── named.conf
├── HelloService
│ ├── Dockerfile
│ └── hello.py
We’ll add more containers to this tree in future steps.
Step 3: Create a docker-compose.yaml
File¶
Docker compose works like Docker, it wants a description file in a directory. For compose that’s a file called docker-compose.yaml
. Let’s start with a version that shows the awesome power of Docker compose. This file comes from the excellent sample apps on Docker’s website.
version: '3.3'
services:
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress:
depends_on:
- db
image: wordpress:latest
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
volumes:
db_data: {}
Step 4: Test it!¶
Now let’s run our application:
$ docker-compose up
If everything worked your application will be running on localhost
.
Step 5: Add DNS¶
Now let’s add instructions for our DNS server:
dns:
build: DNS
restart: always
ports:
- "53000:53/udp"
This will build the Dockerfile
in the DNS
directory.
$ docker-compose build
$ docker-compose up
Step 6: Add an Apache Server for Files¶
We want to be able to serve files with a plain, fast Apache server. We want the files to be easily accessible from the host so we’ll specify a volume that’s a host path. Add the following to your services:
static:
image: httpd:2
volumes:
- htdocs:/usr/local/apache2/htdocs
Now add this to your volumes:
htdocs:
driver: local
driver_opts:
o: bind
type: none
device: /var/www/html
Step 7: Create our Hello Application¶
Let’s add a Python application to our site. We’ll reuse the Hello app from a few weeks ago. Add the following to your services:
hello:
build: HelloService
That will build and run our HelloService container.
Step 8: Add a Proxy Server¶
Finally, it’s time to glue all of our services together. We want them to all be accessible from a single host. We’ll use a front-end load balancer and proxy to enable access to different parts of our application. The Caddy web server is fast, easy, efficient and made for containerization. Create a directory called Proxy
and put two file in it Dockerfile
and Caddyfile
.
Step 8.1: Dockerfile¶
FROM caddy:2
COPY Caddyfile /etc/caddy/Caddyfile
Step 8.2: Caddyfile¶
# The name of your host:
# Use localhost for testing
# Replace this with your real host when you're ready to deploy
localhost
# URL patter to access our Hello app
route /hello/* {
uri strip_prefix /hello
reverse_proxy hello:5000
}
# URL patter to access our static files
route /static/* {
uri strip_prefix /static
reverse_proxy static:80
}
# Default URL pattern goes to Wordpress
reverse_proxy * wordpress:80
Step 8.3: Add the Proxy¶
Now let’s add the proxy service to our docker-compose.yaml
file.
proxy:
build: Proxy
depends_on:
- dns
- wordpress
- hello
- static
restart: always
ports:
- "8000:80"
- "8443:443"
Caddy enable SSL by default so we must expose 80 and 443. The dependencies say that we should not start the proxy server until all of the other services are ready.
Step 8.4: Remove Port 8000 From the Wordpress Configuration¶
Important! You stack won’t start unless you do this!
Remove the following lines from the configuration of the wordpress
container:
ports:
- "8000:80"
Step 9: Test the Stack¶
Now let’s test the full stack.
$ docker-compose build
$ docker-compose up
If it works the following URL will be available:
Wordpress: https://localhost:8443/
HelloApp: https://localhost:8443/hello
Files in
/var/www
: https://localhost:8443/static
Step 10: Go to Production¶
Moving the stack to your AWS machine takes a few tweaks. Do the following:
Change port numbers in
docker-compose.yaml
to be production ports:8000 -> 80
8443 -> 443
53000 -> 53/udp
Change the passwords for the MySQL root user and the wordpress user.
Replace
localhost
inCaddyfile
with the name of your server.
The last step is important if you want a real certificate issued to you by Let’s Encrypt.