Docker Compose describes a whole application in a single file: the program, the database, the networks between them and the volumes where the data lives. One command, docker compose up -d, brings it all up. Here is an example with an application and PostgreSQL, on a VPS that already has Docker (here is how). The same layout works for MariaDB or MySQL: you change the image and the variables.
Putting the project together
| 1 |
Create a folder just for the project and go into it: mkdir my-project && cd my-project. The folder name becomes the project name in Compose.
|
|
| 2 |
Create the .env file with the passwords, and protect it: DB_PASSWORD=put-a-long-random-password-herechmod 600 .env. If you use Git, add .env to .gitignore. Never publish it.
|
|
| 3 |
Create the compose.yaml file (the name docker-compose.yml works too):services: app: build: . restart: unless-stopped env_file: .env environment: DB_HOST: db ports: - "127.0.0.1:3000:3000" depends_on: db: condition: service_healthy db: image: postgres:16 restart: unless-stopped environment: POSTGRES_USER: appuser POSTGRES_PASSWORD: ${DB_PASSWORD} POSTGRES_DB: appdb volumes: - db_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U appuser -d appdb"] interval: 10s timeout: 5s retries: 5 volumes: db_data:
|
|
| 4 |
Bring it up and check the state: docker compose up -d docker compose ps docker compose logs -f appCompose creates a private network for the project.
|
|
What each part does
| Part |
What it does |
Why it is like that |
DB_HOST: db |
The application finds the database by the service name. |
Inside the Compose network you do not use localhost or an IP: each service is a separate computer. |
127.0.0.1:3000:3000 |
Publishes the application port on the server itself only. |
What shows it to the world is a proxy with HTTPS: see nginx as a reverse proxy. |
No port on db |
The database cannot be reached from outside. |
That is what you want. Other services reach it over the internal network. |
db_data (volume) |
Where the database data is kept. |
Without a volume, deleting the container deletes the data. |
healthcheck and service_healthy |
The application starts only when the database already accepts connections. |
depends_on alone only waits for the container to exist, not to be ready. |
The connection address, inside the application, looks like this: postgres://appuser:PASSWORD@db:5432/appdb. If the password has special characters (@, :, /), they must be encoded in the address, or pick one without them.
|
The POSTGRES_* variables only count the first time. They create the database when the volume is empty. If you change the password in the file after the database exists, the database does not change, and the application can no longer log in. You change it with a command inside the database. And docker compose down -v deletes the volumes, meaning the data: without -v, a down only removes the containers.
|
|
The VPS has to be yours, with root. If you do not have one yet, see the plans: Docker and the application are on your side, the network and the server on ours.
See the VPS servers
|
RECOMMENDED PRODUCT Web hosting with cPanel Domain and SSL included, daily backups and the panel you already know. from $5.36/mo (3-year plan, with coupon) See plans |