Skip to main content

Using Docker

Docker is a technology which allows you to run your Vendure application inside a container. The default installation with @vendure/create includes a sample Dockerfile:

Dockerfile
FROM node:16

WORKDIR /usr/src/app

COPY package.json ./
COPY package-lock.json ./
RUN npm install --production
COPY . .
RUN npm run build

This Dockerfile can then be built into an "image" using:

docker build -t vendure .

This same image can be used to run both the Vendure server and the worker:

# Run the server
docker run -dp 3000:3000 --name vendure-server vendure npm run start:server

# Run the worker
docker run -dp 3000:3000 --name vendure-worker vendure npm run start:worker

Here is a breakdown of the command used above:

  • docker run - run the image we created with docker build
  • -dp 3000:3000 - the -d flag means to run in "detached" mode, so it runs in the background and does not take control of your terminal. -p 3000:3000 means to expose port 3000 of the container (which is what Vendure listens on by default) as port 3000 on your host machine.
  • --name vendure-server - we give the container a human-readable name.
  • vendure - we are referencing the tag we set up during the build.
  • npm run start:server - this last part is the actual command that should be run inside the container.

Docker Compose​

Managing multiple docker containers can be made easier using Docker Compose. In the below example, we use the same Dockerfile defined above, and we also define a Postgres database to connect to:

version: "3"
services:
server:
build:
context: .
dockerfile: Dockerfile
ports:
- 3000:3000
command: ["npm", "run", "start:server"]
volumes:
- /usr/src/app
environment:
DB_HOST: database
DB_PORT: 5432
DB_NAME: vendure
DB_USERNAME: postgres
DB_PASSWORD: password
worker:
build:
context: .
dockerfile: Dockerfile
command: ["npm", "run", "start:worker"]
volumes:
- /usr/src/app
environment:
DB_HOST: database
DB_PORT: 5432
DB_NAME: vendure
DB_USERNAME: postgres
DB_PASSWORD: password
database:
image: postgres
volumes:
- /var/lib/postgresql/data
ports:
- 5432:5432
environment:
POSTGRES_PASSWORD: password
POSTGRES_DB: vendure

Kubernetes​

Kubernetes is used to manage multiple containerized applications. This deployment starts the shop container we created above as both worker and server.

apiVersion: apps/v1
kind: Deployment
metadata:
name: vendure-shop
spec:
selector:
matchLabels:
app: vendure-shop
replicas: 1
template:
metadata:
labels:
app: vendure-shop
spec:
containers:
- name: server
image: vendure-shop:latest
command:
- node
args:
- "dist/index.js"
env:
# your env config here
ports:
- containerPort: 3000

- name: worker
image: vendure-shop:latest
imagePullPolicy: Always
command:
- node
args:
- "dist/index-worker.js"
env:
# your env config here
ports:
- containerPort: 3000

Health/Readiness Checks​

If you wish to deploy with Kubernetes or some similar system, you can make use of the health check endpoints.

Server​

This is a regular REST route (note: not GraphQL), available at /health.

REQUEST: GET http://localhost:3000/health
{
"status": "ok",
"info": {
"database": {
"status": "up"
}
},
"error": {},
"details": {
"database": {
"status": "up"
}
}
}

Health checks are built on the Nestjs Terminus module. You can also add your own health checks by creating plugins that make use of the HealthCheckRegistryService.

Worker​

Although the worker is not designed as an HTTP server, it contains a minimal HTTP server specifically to support HTTP health checks. To enable this, you need to call the startHealthCheckServer() method after bootstrapping the worker:

bootstrapWorker(config)
.then(worker => worker.startJobQueue())
.then(worker => worker.startHealthCheckServer({ port: 3020 }))
.catch(err => {
console.log(err);
});

This will make the /health endpoint available. When the worker instance is running, it will return the following:

REQUEST: GET http://localhost:3020/health
{
"status": "ok"
}