Skip to content

Commit 61440ba

Browse files
committed
fix: deployment with Docker Compose
1 parent de3d1fe commit 61440ba

File tree

1 file changed

+69
-56
lines changed

1 file changed

+69
-56
lines changed

deployment/docker-compose.md

Lines changed: 69 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,97 @@
11
# Deploying with Docker Compose
22

3-
While [Docker Compose](https://docs.docker.com/compose/) is mainly known and used in a development environment, it [can
4-
actually be used in production too](https://docs.docker.com/compose/production/). This is especially suitable for prototyping
3+
While [Docker Compose](https://docs.docker.com/compose/) is mainly known and used in a development environment, it [can be used in production too](https://docs.docker.com/compose/production/). This is especially suitable for prototyping
54
or small-scale deployments, where the robustness (and the associated complexity) of [Kubernetes](kubernetes.md) is not
65
required.
76

8-
It is recommended that you build the Docker images in a [CI (continuous integration)](https://en.wikipedia.org/wiki/Continuous_integration)
9-
job, or failing which, on your development machine. The built images should then be pushed to a [container registry](https://docs.docker.com/registry/introduction/),
10-
e.g. [Docker Hub](https://hub.docker.com/), [Google Container Registry](https://cloud.google.com/container-registry/),
11-
[GitLab Container Registry](https://docs.gitlab.com/ee/user/packages/container_registry/). On the production server, you
12-
would pull the pre-built images from the container registry. This maintains a separation of concerns between the build
13-
environment and the production environment.
7+
API Platform provides Docker images, and a Docker Compose definition optimized for production usage.
8+
In this tutorial, we will learn how to deploy our Symfony application on a single server using Docker Compose.
149

15-
## Deploying for Production
10+
Note: this tutorial has been adapted from [the Symfony Docker documentation](https://github.com/dunglas/symfony-docker/blob/main/docs/production.md).
1611

17-
To build images for production, you have to use the `docker-compose.prod.yml` file with Docker Compose.
12+
## Preparing a Server
1813

19-
## Building and Pushing the Docker Images
14+
To deploy your application in production, you need a server.
15+
In this tutorial we will use a virtual machine provided by DigitalOcean, but any Linux server can work.
16+
If you already have a Linux server with Docker Compose installed, you can skip straight to [the next section](#configuring-a-domain-name).
2017

21-
These steps should be performed in a CI job (recommended) or on your development machine.
18+
Otherwise, use [this affiliate link](https://m.do.co/c/5d8aabe3ab80) to get $100 of free credit, create an account, then click on "Create a Droplet".
19+
Then, click on the "Marketplace" tab under the "Choose an image" section and search for the app named "Docker".
20+
This will provision an Ubuntu server with the latest versions of Docker and Docker Compose already installed!
2221

23-
1. Make sure the environment variables required for the build are set.
22+
To test, the cheapest plan will be enough, but for real production usage you'll probably want to pick a plan in the "general purpose" section that will fit your needs.
2423

25-
If you are building the images in a CI job, these environment variables should be set as part of your CI job's environment.
24+
![Deploying a Symfony app on DigitalOcean with Docker Compose](digitalocean-droplet.png)
2625

27-
If you are building on your development machine, you could set the environment variables in the `.env` file at the
28-
top level of the distribution project (not to be confused with `api/.env` which is used by the Symfony application).
29-
For example:
26+
You can keep the defaults for other settings, or tweak them according to your needs.
27+
Don't forget to add your SSH key or to create a password then press the "Finalize and create" button.
3028

31-
```shell
32-
ADMIN_IMAGE=registry.example.com/api-platform/admin
33-
CLIENT_IMAGE=registry.example.com/api-platform/client
34-
NGINX_IMAGE=registry.example.com/api-platform/nginx
35-
PHP_IMAGE=registry.example.com/api-platform/php
36-
REACT_APP_API_ENTRYPOINT=https://api.example.com
37-
VARNISH_IMAGE=registry.example.com/api-platform/varnish
38-
```
29+
Then, wait a few seconds while your Droplet is provisioning.
30+
When your Droplet is ready, use SSH to connect:
3931

40-
**Note**: `REACT_APP_API_ENTRYPOINT` must be an exact match of the target domain name where your API will be accessed
41-
from, since its value is [embedded during build time](https://create-react-app.dev/docs/adding-custom-environment-variables).
42-
See [this discussion for possible workarounds](https://github.com/facebook/create-react-app/issues/2353) if this limitation
43-
is unacceptable for your project.
32+
```console
33+
ssh root@<droplet-ip>
34+
```
4435

45-
2. Build the Docker images:
36+
## Configuring a Domain Name
4637

47-
```shell
48-
docker-compose -f docker-compose.yml -f docker-compose.prod.yml build --pull
49-
```
38+
In most cases, you'll want to associate a domain name to your website.
39+
If you don't own a domain name yet, you'll have to buy one through a registrar.
40+
Use [this affiliate link](https://gandi.link/f/93650337) to redeem a 20% discount at Gandi.net.
5041

51-
3. Push the built images to the container registry:
42+
Then create a DNS record of type `A` for your domain name pointing to the IP address of your server.
5243

53-
```shell
54-
docker-compose -f docker-compose.yml -f docker-compose.prod.yml push
55-
```
44+
Example:
5645

57-
## Pulling the Docker Images and Running the Services
46+
```dns
47+
your-domain-name.example.com. IN A 207.154.233.113
48+
````
5849
59-
These steps should be performed on the production server.
50+
Example in Gandi's UI:
6051
61-
1. Make sure the environment variables required are set.
52+
![Creating a DNS record at Gandi.net](gandi-dns.png)
6253
63-
You could set the environment variables in the `.env` file at the top level of the distribution project (not to be
64-
confused with `api/.env` which is used by the Symfony application). For example:
54+
Note: Let's Encrypt, the service used by default by API Platform to automatically generate a TLS certificate doesn't support using bare IP addresses.
55+
Using a domain name is mandatory to use Let's Encrypt.
6556
66-
```shell
67-
SERVER_NAME=api.example.com
68-
MERCURE_PUBLISHER_JWT_KEY=someKey
69-
MERCURE_SUBSCRIBER_JWT_KEY=someKey
70-
```
57+
## Deploying
7158
72-
**Important**: Please make sure to change all the passwords, keys and secret values to your own.
59+
Copy your project on the server using `git clone`, `scp` or any other tool that may fit your need.
60+
If you use GitHub, you may want to use [a deploy key](https://docs.github.com/en/developers/overview/managing-deploy-keys#deploy-keys).
61+
Deploy keys are also [supported by GitLab](https://docs.gitlab.com/ee/user/project/deploy_keys/).
7362
74-
2. Pull the Docker images.
63+
Example with Git:
7564
76-
```console
77-
docker-compose -f docker-compose.yml -f docker-compose.prod.yml pull
78-
```
65+
```console
66+
git clone git@github.com:<username>/<project-name>.git
67+
```
7968

80-
3. Bring up the services.
69+
Go into the directory containing your project (`<project-name>`), and start the app in production mode:
8170

82-
```console
83-
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
84-
```
71+
```console
72+
SERVER_NAME=your-domain-name.example.com \
73+
APP_SECRET=ChangeMe \
74+
CADDY_MERCURE_JWT_SECRET=ChangeMe \
75+
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
76+
```
77+
78+
Be sure to replace `your-domain-name.example.com` by your actual domain name and to set the values of `APP_SECRET`, `CADDY_MERCURE_JWT_SECRET` to cryptographically secure random values.
79+
80+
Your server is up and running, and a Let's Encrypt HTTPS certificate has been automatically generated for you.
81+
Go to `https://your-domain-name.example.com` and enjoy!
82+
83+
## Disabling HTTPS
84+
85+
Alternatively, if you don't want to expose an HTTPS server but only an HTTP one, run the following command:
86+
87+
```console
88+
SERVER_NAME=:80 \
89+
APP_SECRET=ChangeMe \
90+
CADDY_MERCURE_JWT_SECRET=ChangeMe \
91+
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
92+
```
93+
94+
## Deploying on Multiple Nodes
95+
96+
If you want to deploy your app on a cluster of machines, you can use [Docker Swarm](https://docs.docker.com/engine/swarm/stack-deploy/),
97+
which is compatible with the provided Compose files.

0 commit comments

Comments
 (0)