mirror of
https://gitlab.dit.htwk-leipzig.de/htwk-software/htwkalender-pwa.git
synced 2025-07-16 09:38:51 +02:00
Merge branch 'add-deployment' into 'main'
Add deployment and improve Dockerfiles and CICD See merge request ekresse/htwkalender!17
This commit is contained in:
@ -2,7 +2,8 @@ stages:
|
||||
- lint
|
||||
- build
|
||||
- test
|
||||
- docker
|
||||
- oci-build
|
||||
- deploy
|
||||
|
||||
lint-frontend:
|
||||
image: node:lts
|
||||
@ -29,7 +30,7 @@ lint-backend:
|
||||
|
||||
|
||||
build-backend:
|
||||
image: golang:1.21-alpine
|
||||
image: golang:alpine
|
||||
stage: build
|
||||
rules:
|
||||
- changes:
|
||||
@ -58,7 +59,7 @@ build-frontend:
|
||||
- frontend/build
|
||||
|
||||
test-backend:
|
||||
image: golang:1.21-alpine
|
||||
image: golang:alpine
|
||||
stage: test
|
||||
rules:
|
||||
- changes:
|
||||
@ -83,11 +84,10 @@ test-frontend:
|
||||
- lint-frontend
|
||||
|
||||
build-backend-image:
|
||||
stage: docker
|
||||
image: docker:20.10.16
|
||||
stage: oci-build
|
||||
image: docker:latest
|
||||
services:
|
||||
- name: docker:20.10.16-dind
|
||||
alias: docker
|
||||
- docker:dind
|
||||
tags:
|
||||
- image
|
||||
variables:
|
||||
@ -96,22 +96,19 @@ build-backend-image:
|
||||
DOCKER_TLS_CERTDIR: "/certs"
|
||||
DOCKER_TLS_VERIFY: 1
|
||||
DOCKER_CERT_PATH: "/certs/client"
|
||||
script:
|
||||
- cd backend
|
||||
before_script:
|
||||
- docker login -u $CI_DOCKER_REGISTRY_USER -p $CI_DOCKER_REGISTRY_PASSWORD $CI_DOCKER_REGISTRY
|
||||
- docker build -t htwkalender-backend$IMAGE_TAG .
|
||||
- docker tag htwkalender-backend$IMAGE_TAG $CI_DOCKER_REGISTRY_USER/htwkalender:backend
|
||||
- docker push $CI_DOCKER_REGISTRY_USER/htwkalender:backend
|
||||
only:
|
||||
- main
|
||||
- development
|
||||
script:
|
||||
- docker build --pull -t $CI_DOCKER_REGISTRY_REPO:backend -f ./backend/Dockerfile --target prod ./backend
|
||||
- docker push $CI_DOCKER_REGISTRY_REPO:backend
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == "main"
|
||||
|
||||
build-frontend-image:
|
||||
stage: docker
|
||||
image: docker:20.10.16
|
||||
stage: oci-build
|
||||
image: docker:latest
|
||||
services:
|
||||
- name: docker:20.10.16-dind
|
||||
alias: docker
|
||||
- docker:dind
|
||||
tags:
|
||||
- image
|
||||
variables:
|
||||
@ -120,12 +117,36 @@ build-frontend-image:
|
||||
DOCKER_TLS_CERTDIR: "/certs"
|
||||
DOCKER_TLS_VERIFY: 1
|
||||
DOCKER_CERT_PATH: "/certs/client"
|
||||
script:
|
||||
- cd frontend
|
||||
before_script:
|
||||
- docker login -u $CI_DOCKER_REGISTRY_USER -p $CI_DOCKER_REGISTRY_PASSWORD $CI_DOCKER_REGISTRY
|
||||
- docker build -f Dockerfile_prod -t htwkalender-frontend$IMAGE_TAG .
|
||||
- docker tag htwkalender-frontend$IMAGE_TAG $CI_DOCKER_REGISTRY_USER/htwkalender:frontend
|
||||
- docker push $CI_DOCKER_REGISTRY_USER/htwkalender:frontend
|
||||
only:
|
||||
- main
|
||||
- development
|
||||
script:
|
||||
- docker build --pull -t $CI_DOCKER_REGISTRY_REPO:frontend -f ./frontend/Dockerfile --target prod .
|
||||
- docker push $CI_DOCKER_REGISTRY_REPO:frontend
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == "main"
|
||||
|
||||
deploy-all:
|
||||
stage: deploy
|
||||
image: alpine:latest
|
||||
before_script:
|
||||
- apk add --no-cache openssh-client sed # install dependencies
|
||||
- eval $(ssh-agent -s) # set some ssh variables
|
||||
- ssh-add <(echo "$CI_SSH_KEY" | tr -d '\r')
|
||||
script:
|
||||
# replace some placeholders
|
||||
- sed -i -e "s|DOCKER_REGISTRY_REPO|$CI_DOCKER_REGISTRY_REPO|" docker-compose.prod.yml
|
||||
# upload necessary files to the server
|
||||
- >
|
||||
scp -P $CI_SSH_PORT -o StrictHostKeyChecking=no -o LogLevel=ERROR ./docker-compose.prod.yml ./reverseproxy.conf
|
||||
$CI_SSH_USER@$CI_SSH_HOST:/home/$CI_SSH_USER/docker/htwkalender/
|
||||
# ssh to the server and start the service
|
||||
- >
|
||||
ssh -p $CI_SSH_PORT -o StrictHostKeyChecking=no -o LogLevel=ERROR $CI_SSH_USER@$CI_SSH_HOST
|
||||
"cd /home/$CI_SSH_USER/docker/htwkalender/ &&
|
||||
docker login -u $CI_DOCKER_REGISTRY_USER -p $CI_DOCKER_REGISTRY_PASSWORD $CI_DOCKER_REGISTRY &&
|
||||
docker compose -f ./docker-compose.prod.yml down && docker compose -f ./docker-compose.prod.yml up -d --remove-orphans && docker logout"
|
||||
needs:
|
||||
- build-frontend-image
|
||||
- build-backend-image
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == "main"
|
||||
|
@ -1,18 +1,31 @@
|
||||
FROM golang:1.21.6
|
||||
# build stage
|
||||
FROM golang:alpine AS build
|
||||
|
||||
# Set the Current Working Directory inside the container
|
||||
WORKDIR /app
|
||||
|
||||
# Copy go mod and sum files
|
||||
COPY go.mod go.sum ./
|
||||
RUN go mod download
|
||||
|
||||
# Copy the source from the current directory to the Working Directory inside the container
|
||||
COPY *.go ./
|
||||
COPY . .
|
||||
COPY . ./
|
||||
# download needed modules
|
||||
RUN apk add --no-cache --update go gcc g++ && \
|
||||
go mod download && \
|
||||
CGO_ENABLED=1 GOOS=linux go build -o /htwkalender
|
||||
|
||||
# Build the Go app
|
||||
RUN CGO_ENABLED=1 GOOS=linux go build -o /htwkalender
|
||||
# production stage
|
||||
FROM alpine:latest AS prod
|
||||
|
||||
# Expose port 8080 to the outside world
|
||||
EXPOSE 8080
|
||||
WORKDIR /htwkalender
|
||||
|
||||
ARG USER=ical
|
||||
RUN adduser -Ds /bin/sh $USER && \
|
||||
chown $USER:$USER ./
|
||||
|
||||
USER $USER
|
||||
RUN mkdir -p data
|
||||
|
||||
# copies executable from build container
|
||||
COPY --chown=$USER:$USER --from=build /htwkalender ./
|
||||
|
||||
# Expose port 8090 to the outside world
|
||||
EXPOSE 8090
|
||||
|
||||
ENTRYPOINT ["./htwkalender", "serve"]
|
||||
|
@ -1,6 +1,6 @@
|
||||
module htwkalender
|
||||
|
||||
go 1.21
|
||||
go 1.21.6
|
||||
|
||||
require (
|
||||
github.com/PuerkitoBio/goquery v1.8.1
|
||||
|
@ -1,14 +1,22 @@
|
||||
package date
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
_ "time/tzdata"
|
||||
)
|
||||
|
||||
func GetDateFromWeekNumber(year int, weekNumber int, dayName string) (time.Time, error) {
|
||||
// Create a time.Date for the first day of the year
|
||||
europeTime, _ := time.LoadLocation("Europe/Berlin")
|
||||
europeTime, err := time.LoadLocation("Europe/Berlin")
|
||||
|
||||
if err != nil {
|
||||
slog.Error("Failed to load location: ", err)
|
||||
return time.Time{}, err
|
||||
}
|
||||
|
||||
firstDayOfYear := time.Date(year, time.January, 1, 0, 0, 0, 0, europeTime)
|
||||
|
||||
// Calculate the number of days to add to reach the desired week
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
_ "time/tzdata"
|
||||
)
|
||||
|
||||
func Test_getDateFromWeekNumber(t *testing.T) {
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/jordic/goics"
|
||||
_ "time/tzdata"
|
||||
)
|
||||
|
||||
// IcalModel local type for EmitICal function
|
||||
|
@ -2,25 +2,32 @@ version: "3.9"
|
||||
|
||||
services:
|
||||
htwkalender-backend:
|
||||
build:
|
||||
dockerfile: Dockerfile
|
||||
context: ./backend
|
||||
image: DOCKER_REGISTRY_REPO:backend # DOCKER_REGISTRY_REPO will be replaced by CI
|
||||
command: "--http=0.0.0.0:8090 --dir=/htwkalender/data/pb_data"
|
||||
pull_policy: always
|
||||
# open port 8090
|
||||
ports:
|
||||
- "8090:8090"
|
||||
command: "/htwkalender serve --http=0.0.0.0:8090 --dir=/pb_data"
|
||||
volumes:
|
||||
- ./backend/pb_data:/pb_data
|
||||
- pb_data:/htwkalender/data
|
||||
|
||||
htwkalender-frontend:
|
||||
build:
|
||||
context: ./frontend
|
||||
dockerfile: Dockerfile_prod
|
||||
image: DOCKER_REGISTRY_REPO:frontend # DOCKER_REGISTRY_REPO will be replaced by CI
|
||||
pull_policy: always
|
||||
ports:
|
||||
- "8000:8000"
|
||||
depends_on:
|
||||
- htwkalender-backend
|
||||
|
||||
rproxy:
|
||||
image: nginx:stable
|
||||
image: bitnami/nginx:1.25
|
||||
volumes:
|
||||
- ./reverseproxy.conf:/etc/nginx/nginx.conf
|
||||
- ./reverseproxy.conf:/opt/bitnami/nginx/conf/nginx.conf
|
||||
depends_on:
|
||||
- htwkalender-backend
|
||||
- htwkalender-frontend
|
||||
ports:
|
||||
- "80:80"
|
||||
|
||||
volumes:
|
||||
pb_data:
|
||||
|
@ -5,29 +5,33 @@ services:
|
||||
build:
|
||||
dockerfile: Dockerfile
|
||||
context: ./backend
|
||||
target: prod
|
||||
command: "--http=0.0.0.0:8090 --dir=/htwkalender/data/pb_data"
|
||||
# open port 8090
|
||||
ports:
|
||||
- "8090:8090"
|
||||
command: "/htwkalender serve --http=0.0.0.0:8090 --dir=/pb_data"
|
||||
- "8090:8090"
|
||||
volumes:
|
||||
- ./backend/pb_data:/pb_data
|
||||
- pb_data:/htwkalender/data
|
||||
|
||||
htwkalender-frontend:
|
||||
volumes:
|
||||
- ./frontend/src:/app/src
|
||||
build:
|
||||
dockerfile: Dockerfile
|
||||
context: ./frontend
|
||||
target: dev
|
||||
command: "npm run dev"
|
||||
# open port 8000
|
||||
ports:
|
||||
- "8000:8000"
|
||||
command: "npm run dev"
|
||||
- "8000:8000"
|
||||
|
||||
rproxy:
|
||||
image: nginx:stable
|
||||
image: bitnami/nginx:1.25
|
||||
volumes:
|
||||
- ./reverseproxy.conf:/etc/nginx/nginx.conf
|
||||
- ./reverseproxy.conf:/opt/bitnami/nginx/conf/nginx.conf
|
||||
depends_on:
|
||||
- htwkalender-backend
|
||||
- htwkalender-frontend
|
||||
ports:
|
||||
- "80:80"
|
||||
|
||||
volumes:
|
||||
pb_data:
|
||||
|
@ -1,7 +1,26 @@
|
||||
FROM node:lts-alpine3.18
|
||||
# build stage
|
||||
FROM node:lts-alpine AS build
|
||||
|
||||
WORKDIR /app
|
||||
COPY frontend/package*.json ./
|
||||
RUN npm ci
|
||||
COPY frontend/ ./
|
||||
RUN npm run build
|
||||
|
||||
# development stage
|
||||
FROM node:lts-alpine AS dev
|
||||
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN npm install
|
||||
COPY ./ ./
|
||||
COPY . ./
|
||||
|
||||
# production stage
|
||||
# https://hub.docker.com/r/bitnami/nginx -> always run as non-root user
|
||||
FROM bitnami/nginx:1.25 AS prod
|
||||
|
||||
# copy build files from build container
|
||||
COPY --from=build /app/dist /app
|
||||
COPY ./frontend/nginx.conf /opt/bitnami/nginx/conf/nginx.conf
|
||||
|
||||
EXPOSE 8000
|
||||
|
@ -1,14 +0,0 @@
|
||||
# build stage
|
||||
FROM node:lts-alpine3.18 as build-stage
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
# production stage
|
||||
FROM nginx:stable as production-stage
|
||||
COPY --from=build-stage /app/dist /usr/share/nginx/html
|
||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||
EXPOSE 8000
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
@ -1,47 +1,44 @@
|
||||
server {
|
||||
listen 8000;
|
||||
listen [::]:8000;
|
||||
server_name localhost;
|
||||
worker_processes 4;
|
||||
|
||||
#access_log /var/log/nginx/host.access.log main;
|
||||
error_log /opt/bitnami/nginx/logs/error.log;
|
||||
pid /opt/bitnami/nginx/tmp/nginx.pid;
|
||||
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
|
||||
#necessary to display vue subpage
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
#error_page 404 /404.html;
|
||||
|
||||
# redirect server error pages to the static page /50x.html
|
||||
#
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
|
||||
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
|
||||
#
|
||||
#location ~ \.php$ {
|
||||
# proxy_pass http://127.0.0.1;
|
||||
#}
|
||||
|
||||
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
|
||||
#
|
||||
#location ~ \.php$ {
|
||||
# root html;
|
||||
# fastcgi_pass 127.0.0.1:9000;
|
||||
# fastcgi_index index.php;
|
||||
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
|
||||
# include fastcgi_params;
|
||||
#}
|
||||
|
||||
# deny access to .htaccess files, if Apache's document root
|
||||
# concurs with nginx's one
|
||||
#
|
||||
#location ~ /\.ht {
|
||||
# deny all;
|
||||
#}
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
include mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
access_log /opt/bitnami/nginx/logs/proxy_access.log;
|
||||
error_log /opt/bitnami/nginx/logs/proxy_error.log;
|
||||
|
||||
sendfile on;
|
||||
keepalive_timeout 180s;
|
||||
send_timeout 180s;
|
||||
|
||||
client_body_temp_path /opt/bitnami/nginx/tmp/client_temp;
|
||||
proxy_temp_path /opt/bitnami/nginx/tmp/proxy_temp_path;
|
||||
fastcgi_temp_path /opt/bitnami/nginx/tmp/fastcgi_temp;
|
||||
uwsgi_temp_path /opt/bitnami/nginx/tmp/uwsgi_temp;
|
||||
scgi_temp_path /opt/bitnami/nginx/tmp/scgi_temp;
|
||||
|
||||
server {
|
||||
listen 8000;
|
||||
listen [::]:8000;
|
||||
server_name localhost;
|
||||
|
||||
location / {
|
||||
root /opt/bitnami/nginx/html;
|
||||
index index.html index.htm;
|
||||
|
||||
#necessary to display vue subpage
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /opt/bitnami/nginx/html;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
worker_processes 1;
|
||||
worker_processes 4;
|
||||
|
||||
error_log /var/log/nginx/error.log;
|
||||
pid /var/run/nginx.pid;
|
||||
error_log /opt/bitnami/nginx/logs/error.log;
|
||||
pid /opt/bitnami/nginx/tmp/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
@ -11,8 +11,8 @@ http {
|
||||
include mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
access_log /var/log/nginx/proxy_access.log;
|
||||
error_log /var/log/nginx/proxy_error.log;
|
||||
access_log /opt/bitnami/nginx/logs/proxy_access.log;
|
||||
error_log /opt/bitnami/nginx/logs/proxy_error.log;
|
||||
|
||||
sendfile on;
|
||||
keepalive_timeout 180s;
|
||||
@ -23,6 +23,12 @@ http {
|
||||
POST 1;
|
||||
}
|
||||
|
||||
client_body_temp_path /opt/bitnami/nginx/tmp/client_temp;
|
||||
proxy_temp_path /opt/bitnami/nginx/tmp/proxy_temp_path;
|
||||
fastcgi_temp_path /opt/bitnami/nginx/tmp/fastcgi_temp;
|
||||
uwsgi_temp_path /opt/bitnami/nginx/tmp/uwsgi_temp;
|
||||
scgi_temp_path /opt/bitnami/nginx/tmp/scgi_temp;
|
||||
|
||||
proxy_cache_path /dev/shm levels=1:2 keys_zone=mcache:16m inactive=600s max_size=512m;
|
||||
proxy_cache_methods GET HEAD;
|
||||
proxy_cache_min_uses 1;
|
||||
|
Reference in New Issue
Block a user