|
1 | 1 | # Deploying with Docker Compose
|
2 | 2 |
|
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 |
5 | 4 | or small-scale deployments, where the robustness (and the associated complexity) of [Kubernetes](kubernetes.md) is not
|
6 | 5 | required.
|
7 | 6 |
|
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. |
14 | 9 |
|
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). |
16 | 11 |
|
17 |
| -To build images for production, you have to use the `docker-compose.prod.yml` file with Docker Compose. |
| 12 | +## Preparing a Server |
18 | 13 |
|
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). |
20 | 17 |
|
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! |
22 | 21 |
|
23 |
| -1. Make sure the environment variables required for the build are set. |
| 22 | +For test purposes, the cheapest plan will be enough. For real production usage, you'll probably want to pick a plan in the "general purpose" section that will fit your needs. |
24 | 23 |
|
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 | + |
26 | 25 |
|
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. |
30 | 28 |
|
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: |
39 | 31 |
|
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 | +``` |
44 | 35 |
|
45 |
| -2. Build the Docker images: |
| 36 | +## Configuring a Domain Name |
46 | 37 |
|
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 with 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. |
50 | 41 |
|
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. |
52 | 43 |
|
53 |
| - ```shell |
54 |
| - docker-compose -f docker-compose.yml -f docker-compose.prod.yml push |
55 |
| - ``` |
| 44 | +Example: |
56 | 45 |
|
57 |
| -## Pulling the Docker Images and Running the Services |
| 46 | +```dns |
| 47 | +your-domain-name.example.com. IN A 207.154.233.113 |
| 48 | +```` |
58 | 49 |
|
59 |
| -These steps should be performed on the production server. |
| 50 | +Example in Gandi's UI: |
60 | 51 |
|
61 |
| -1. Make sure the environment variables required are set. |
| 52 | + |
62 | 53 |
|
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. |
65 | 56 |
|
66 |
| - ```shell |
67 |
| - SERVER_NAME=api.example.com |
68 |
| - MERCURE_PUBLISHER_JWT_KEY=someKey |
69 |
| - MERCURE_SUBSCRIBER_JWT_KEY=someKey |
70 |
| - ``` |
| 57 | +## Deploying |
71 | 58 |
|
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 needs. |
| 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/). |
73 | 62 |
|
74 |
| -2. Pull the Docker images. |
| 63 | +Example with Git: |
75 | 64 |
|
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 | +``` |
79 | 68 |
|
80 |
| -3. Bring up the services. |
| 69 | +Go into the directory containing your project (`<project-name>`), and start the app in production mode: |
81 | 70 |
|
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 | +POSTGRES_PASSWORD=ChangeMe \ |
| 75 | +CADDY_MERCURE_JWT_SECRET=ChangeMe \ |
| 76 | +docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d |
| 77 | +``` |
| 78 | + |
| 79 | +Be sure to replace `your-domain-name.example.com` with your actual domain name and to set the values of `APP_SECRET`, `CADDY_MERCURE_JWT_SECRET` to cryptographically secure random values. |
| 80 | + |
| 81 | +Your server is up and running, and a Let's Encrypt HTTPS certificate has been automatically generated for you. |
| 82 | +Go to `https://your-domain-name.example.com` and enjoy! |
| 83 | + |
| 84 | +## Deploying on Multiple Nodes |
| 85 | + |
| 86 | +If you want to deploy your app on a cluster of machines, we recommend using [Kubernetes](kubernetes.md). |
| 87 | +You can use [Docker Swarm](https://docs.docker.com/engine/swarm/stack-deploy/), |
| 88 | +which is compatible with the provided Compose files. |
0 commit comments