Skip to content

Commit

Permalink
Publish Docker Containers (#81)
Browse files Browse the repository at this point in the history
* End of day commit

* Configure Frontend container with env variables

* Configure server port

* Connect frontend to backend via docker compose

* Rename nginx config for frontend docker

* Move parts of docker compose deployment to deployment folder

* Add ci for image publishing
  • Loading branch information
georg-schwarz authored Nov 16, 2022
1 parent ec71de4 commit 2c9a287
Show file tree
Hide file tree
Showing 10 changed files with 269 additions and 7 deletions.
76 changes: 76 additions & 0 deletions .github/workflows/publish-docker.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
name: Publish Docker Images

on:
release:
types: [published]

env:
REGISTRY: ghcr.io
FRONTEND_IMAGE_NAME: ${{ github.repository }}-frontend
SERVER_IMAGE_NAME: ${{ github.repository }}-server

jobs:
build-and-push-frontend:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- name: Checkout repository
uses: actions/checkout@v3

- name: Log in to the Container registry
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ env.REGISTRY }}/${{ env.FRONTEND_IMAGE_NAME }}

- name: Build and push image
uses: docker/build-push-action@v3
with:
context: .
file: frontend.Dockerfile
push: true
build-args: REACT_APP_BACKEND_URL='/api'
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

build-and-push-server:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- name: Checkout repository
uses: actions/checkout@v3

- name: Log in to the Container registry
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ env.REGISTRY }}/${{ env.SERVER_IMAGE_NAME }}

- name: Build and push image
uses: docker/build-push-action@v3
with:
context: .
file: server.Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
16 changes: 11 additions & 5 deletions deployment/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
# Deployment

Currently, we only support local deployment. See [Development Setup](../README) in the main README.
## Local Machine

Planned:
See [Development Setup](../README) in the main README.

- Dockerization
- Docker-compose deployment
- Kubernetes deployment
## Docker Compose

- Use the `/deployment/docker/docker-compose.yml`. Change environment variables to change secrets, credentials, etc.
- Build via `docker compose -f deployment/docker/docker-compose.yml build`.
- Run via `docker compose -f deployment/docker/docker-compose.yml up`

## Kubernetes

Upcoming!
60 changes: 60 additions & 0 deletions deployment/docker/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
version: '3.7'

services:
msadoc-frontend:
image: msadoc-frontend
build:
context: ../..
dockerfile: frontend.Dockerfile
args:
REACT_APP_BACKEND_URL: '/api'
labels:
- 'traefik.enable=true'
- 'traefik.http.routers.to-ui.rule=PathPrefix(`/`)'

msadoc-server:
image: msadoc-server
build:
context: ../..
dockerfile: server.Dockerfile
environment:
msadoc_port: 80

msadoc_username: 'myuser'
msadoc_password: '12345'
msadoc_jwt_access_secret: 'mGbDyb$o2!KSYt%XCB8TGKcuK7XfH6Nf@44xg853MFrGRqV7CG'
msadoc_jwt_refresh_secret: 'o*S5rzMzav5T9tniPYAq3e2V8V5ESY%pV8%3%2Q28MQVw49jGU'

msadoc_db_host: 'msadoc-db'
msadoc_db_port: '5432'
msadoc_db_user: 'postgres'
msadoc_db_pw: 'password'
msadoc_db_db: 'msadoc'

msadoc_frontend_url: '/'
labels:
- 'traefik.enable=true'
- 'traefik.http.routers.to-server.rule=PathPrefix(`/api`)'
- 'traefik.http.routers.to-server.middlewares=server-stripprefix@docker'
- 'traefik.http.middlewares.server-stripprefix.stripprefix.prefixes=/api'

msadoc-db:
image: postgres
environment:
POSTGRES_USER: 'postgres'
POSTGRES_PASSWORD: 'password'
POSTGRES_DB: 'msadoc'

msadoc-edge:
image: traefik:v2.9
command:
- '--providers.docker=true' # enable label annotations in compose file
- '--providers.docker.exposedbydefault=false'
- '--entrypoints.web.address=:80'
- --api.insecure # Activates dashboard: don't do that in production
#- "--log.level=DEBUG"
ports:
- '80:80' # HTTP port
- '8080:8080' # Dashboard
volumes:
- '/var/run/docker.sock:/var/run/docker.sock:ro'
15 changes: 15 additions & 0 deletions deployment/docker/frontend.Docker.nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
server {
listen 80;
server_name localhost;

location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html; # redirect all requests to index.html
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
50 changes: 50 additions & 0 deletions frontend.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#----------------------------------------------------------#
# First stage: base image for building frontend app #
#----------------------------------------------------------#
FROM node:16-alpine as base

WORKDIR /build

# Copy package*.json files first in order to make best use of docker layer caching
COPY package*.json ./
COPY frontend/package*.json ./frontend/
COPY client-generated ./client-generated/

# copy rest of the files
COPY *.js ./
COPY frontend/tsconfig* ./frontend/
COPY frontend/*.js ./frontend/
COPY frontend/public ./frontend/public/
COPY frontend/.env* ./frontend/
COPY frontend/src ./frontend/src/

RUN npm ci

#--------------------------------------------------------#
# Second stage: image to build and test node application #
#--------------------------------------------------------#
FROM base as build

ARG REACT_APP_BACKEND_URL

# lint project
RUN npm run lint -w frontend

# build
RUN npm run build -w frontend

#--------------------------------------------#
# Third stage: image to run node application #
#--------------------------------------------#

FROM nginx:1-alpine

# copy static result of builder to the standard nginx webroot
COPY --from=build /build/frontend/build/ /usr/share/nginx/html

# use custom nginx config
COPY deployment/docker/frontend.Docker.nginx.conf /etc/nginx/conf.d/default.conf

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]
4 changes: 4 additions & 0 deletions frontend/.env.production
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
DISABLE_ESLINT_PLUGIN=true
PORT=$FRONTEND_PORT

REACT_APP_BACKEND_URL=$BACKEND_URL
49 changes: 49 additions & 0 deletions server.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#----------------------------------------------------------#
# First stage: base image for building server app #
#----------------------------------------------------------#
FROM node:16-alpine as base

WORKDIR /build

# Copy package*.json files first in order to make best use of docker layer caching
COPY package*.json ./
COPY server/package*.json ./server/

# npm clean slate install to get reproducible builds and quicker installs
RUN npm ci

# copy rest of the files
COPY *.js ./
COPY server/tsconfig* ./server/
COPY server/*.js ./server/
COPY server/src ./server/src/

#--------------------------------------------------------#
# Second stage: image to build and test node application #
#--------------------------------------------------------#
FROM base as build

# lint project
RUN npm run lint -w server

# build
RUN npm run build -w server

# run unit test
RUN npm run test -w server

#--------------------------------------------#
# Third stage: image to run node application #
#--------------------------------------------#
FROM node:16-alpine

WORKDIR /app

COPY --from=build /build/server/dist/ ./dist/
COPY --from=build /build/server/package*.json ./

RUN npm i --omit=dev

EXPOSE 80

CMD [ "npm", "run", "start:prod" ]
2 changes: 1 addition & 1 deletion server/.env.ci
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
HELLO="World"
msadoc_port=3000
msadoc_username="myuser"
msadoc_password="12345"
msadoc_jwt_access_secret="mGbDyb$o2!KSYt%XCB8TGKcuK7XfH6Nf@44xg853MFrGRqV7CG"
Expand Down
1 change: 1 addition & 0 deletions server/.env.dev.local
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
msadoc_port=3000
msadoc_username="myuser"
msadoc_password="12345"
msadoc_jwt_access_secret="mGbDyb$o2!KSYt%XCB8TGKcuK7XfH6Nf@44xg853MFrGRqV7CG"
Expand Down
3 changes: 2 additions & 1 deletion server/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ async function bootstrap() {
origin: configService.getOrThrow('msadoc_frontend_url'),
});

await app.listen(3000);
const port = configService.getOrThrow('msadoc_port');
await app.listen(port);
}
bootstrap();

0 comments on commit 2c9a287

Please sign in to comment.