We will be using Docker, which provides vm-like containers to easily deploy, scale, and replicate. Read more here.
The project has three parts: client, server, and the database. Using docker, we’ll spin up images for each part.
You can download Docker Desktop to have a visual representation of your images and containers.
In /client
, we are adding 3 files: .dockerignore
, Dockerfile
, and default.conf.template
to the root directory.
The .dockerignore
will ignore specific files when creating the image.
build
.dockerignore
**/.git
**/.DS_Store
**/node_modules
Dockerfile
**/npm-debug.log
The Dockerfile
will create the client image used in the container. To create the production build, the script creates a production build of the app, then does it again without Typescript, and finally creates the image with the NGINX reverse-proxy.
FROM node:16-alpine3.12 as builder
WORKDIR /app
COPY package.json ./
COPY package-lock.json ./
COPY tsconfig*.json ./
RUN npm install
COPY . .
RUN npm run build
FROM node:16-alpine3.12 as ts-remover
WORKDIR /app
COPY --from=builder /app/package*.json ./
COPY --from=builder /app/build ./
RUN npm install --only=production
FROM nginx:stable-alpine as production
ENV NODE_ENV production
# Copy built assets from ts-remover
COPY --from=ts-remover /app /usr/share/nginx/html
# Add your nginx.conf
COPY default.conf.template /etc/nginx/templates/
# Expose port
EXPOSE 80
# Start nginx
CMD ["nginx", "-g", "daemon off;"]
The default.conf.template
is used for NGINX to reverse-proxy any requests with /api
prefix to the backend.
<aside>
‼️ If the backend doesn’t use the /api
prefix for its API, then you’ll have to specify the specific server port in all your API requests (i.e. http://domain_name:8080/server-route
). Moreover, you won’t need the location /api
block.
</aside>
server {
listen 80;
location /api {
client_max_body_size 128M;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_redirect off;
proxy_pass <http://server:8080>;
proxy_cache_bypass $http_upgrade;
}
location / {
root /usr/share/nginx/html/;
include /etc/nginx/mime.types;
try_files $uri /index.html;
}
}
In /server
, add two files: .dockerignore
and Dockerfile
.
build
.dockerignore
**/.git
**/.DS_Store
**/node_modules
Dockerfile
**/npm-debug.log
The Dockerfile
creates an image without Typescript.
FROM node:16-alpine3.12 as builder
WORKDIR /app
COPY package.json ./
COPY package-lock.json ./
COPY tsconfig*.json ./
RUN npm install
COPY . .
RUN npm run build
FROM node:16-alpine3.12 as ts-remover
WORKDIR /app
COPY --from=builder /app/package*.json ./
COPY --from=builder /app/build ./
RUN npm install --only=production
# ---------- Release ----------
FROM builder as release
WORKDIR /app
COPY --from=ts-remover /app ./
CMD ["npm", "run", "start:prod"]