[skip-ci] WIP Add docker image
Add website-build-deployment and cron skeleton. Add shadow-cljs.edn - needs config for cljs.
This commit is contained in:
parent
a21c2a4957
commit
76f5b87ec9
14 changed files with 274 additions and 38 deletions
49
README.md
49
README.md
|
@ -2,10 +2,6 @@
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
Unsere Website soll mit k8s laufen.
|
|
||||||
|
|
||||||
Unsere erzeugten images incl. Web-Inhalt sollen nicht öffentlich zugänglich sein.
|
|
||||||
|
|
||||||
A.C.:
|
A.C.:
|
||||||
wir haben ein konzept erstellt, wie wir statische Inhalte ausliefern (git-pull & cron // cicid // manueller pybuilder-run).
|
wir haben ein konzept erstellt, wie wir statische Inhalte ausliefern (git-pull & cron // cicid // manueller pybuilder-run).
|
||||||
|
|
||||||
|
@ -15,33 +11,18 @@ A.C.:
|
||||||
|
|
||||||
c4k holt sich stets die neuesten website-container unterbrechungsfrei.
|
c4k holt sich stets die neuesten website-container unterbrechungsfrei.
|
||||||
|
|
||||||
unsere website läuft mit dem neuen setup und ist unter ipv4 und ipv6 erreichbar.
|
Unsere website läuft mit dem neuen Setup, ist unter ipv4/v6 und unter 1 oder 2 FQDNs erreichbar.
|
||||||
website ist unter 1 oder 2 fqdns erreichbar.
|
|
||||||
|
|
||||||
## Was passiert?
|
## Was passiert?
|
||||||
|
|
||||||
_Frage_ Sollen später Webserver auf den gleichen, laufenden Cluster hinzugefügt werden können?
|
Webserver sollen auf den gleichen, laufenden Cluster hinzugefügt werden können.
|
||||||
|
|
||||||
**Ja:**
|
**c4k**
|
||||||
|
Pro Website je: Ingress -> Service -> Webserver Pod -> Volume Mount -> PVC.
|
||||||
Ein Cluster, 1 Pod für eine Website (WS)
|
Ingress muss die angefragten FQDNS auflösen und weiterleiten.
|
||||||
-> mehrere FQDNs müssen auf einen Cluster Zeigen
|
|
||||||
-> viele Pods für viele WS
|
|
||||||
-> Package einen Webserver mit einer Website
|
|
||||||
-> DNS Routen so einrichten, dass verschiedene FQDNs auf selbe cluster-id zeigen
|
|
||||||
-> Ingress muss die angefragten FQDNS auflösen und weiterleiten
|
|
||||||
|
|
||||||
Anforderungen an Website-Container:
|
|
||||||
nginx-deployment
|
|
||||||
nginx-config -> wie
|
|
||||||
serviceType: LoadBalancer
|
|
||||||
PVC + volume-mount zeigt auf website-data-vol
|
|
||||||
|
|
||||||
**Terraform:**
|
**Terraform:**
|
||||||
FQDNs für verschiedene Websites hinzufügen?
|
Mehrere DNS Einträge auf Terraform Seite für einen Cluster.
|
||||||
Verbindung mit c4k?
|
|
||||||
c4k-Modulname als Teil des FQDNs wird später noch problematisch.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Reading:
|
### Reading:
|
||||||
|
@ -54,20 +35,14 @@ Deploying Nginx:
|
||||||
https://kubernetes.io/docs/tasks/run-application/run-stateless-application-deployment/
|
https://kubernetes.io/docs/tasks/run-application/run-stateless-application-deployment/
|
||||||
https://www.tecmint.com/deploy-nginx-on-a-kubernetes-cluster/
|
https://www.tecmint.com/deploy-nginx-on-a-kubernetes-cluster/
|
||||||
|
|
||||||
|
##
|
||||||
|
|
||||||
|
Definition von Env-Vars im Deployment:
|
||||||
|
AUTHTOKEN - muss konfigurierbar sein
|
||||||
|
REPOZIPURL - muss konfigurierbar sein
|
||||||
|
TARGETDIR - wird aus dem FQDN zusammengesetzt
|
||||||
|
|
||||||
## Struktur
|
Ingress, Service, Certificate, Deployment, Configmap und Volume Mount sollen durch eindeutige, auf FQDN basierenden Namen verbunden sein.
|
||||||
|
|
||||||
1. Baue die statische website
|
|
||||||
|
|
||||||
2. Schieb die Website auf den Server
|
|
||||||
|
|
||||||
3. Liefere die Website mit einem Webserver aus
|
|
||||||
|
|
||||||
## Fragen
|
|
||||||
|
|
||||||
Soll Cryogen auch in einem container laufen?
|
|
||||||
|
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
|
|
||||||
|
|
51
infrastructure/docker-website-build/build.py
Normal file
51
infrastructure/docker-website-build/build.py
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
from os import environ
|
||||||
|
from pybuilder.core import task, init
|
||||||
|
from ddadevops import *
|
||||||
|
import logging
|
||||||
|
|
||||||
|
name = 'c4k-website-build'
|
||||||
|
MODULE = 'docker'
|
||||||
|
PROJECT_ROOT_PATH = '../..'
|
||||||
|
|
||||||
|
class MyBuild(DevopsDockerBuild):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@init
|
||||||
|
def initialize(project):
|
||||||
|
project.build_depends_on('ddadevops>=0.12.4')
|
||||||
|
stage = 'prod'
|
||||||
|
dockerhub_user = environ.get('DOCKERHUB_USER')
|
||||||
|
if not dockerhub_user:
|
||||||
|
dockerhub_user = gopass_field_from_path('meissa/web/docker.com', 'login')
|
||||||
|
dockerhub_password = environ.get('DOCKERHUB_PASSWORD')
|
||||||
|
if not dockerhub_password:
|
||||||
|
dockerhub_password = gopass_password_from_path('meissa/web/docker.com')
|
||||||
|
tag = environ.get('CI_COMMIT_TAG')
|
||||||
|
if not tag:
|
||||||
|
tag = get_tag_from_latest_commit()
|
||||||
|
config = create_devops_docker_build_config(
|
||||||
|
stage, PROJECT_ROOT_PATH, MODULE, dockerhub_user, dockerhub_password, docker_publish_tag=tag)
|
||||||
|
build = MyBuild(project, config)
|
||||||
|
build.initialize_build_dir()
|
||||||
|
|
||||||
|
|
||||||
|
@task
|
||||||
|
def image(project):
|
||||||
|
build = get_devops_build(project)
|
||||||
|
build.image()
|
||||||
|
|
||||||
|
@task
|
||||||
|
def drun(project):
|
||||||
|
build = get_devops_build(project)
|
||||||
|
build.drun()
|
||||||
|
|
||||||
|
@task
|
||||||
|
def publish(project):
|
||||||
|
build = get_devops_build(project)
|
||||||
|
build.dockerhub_login()
|
||||||
|
build.dockerhub_publish()
|
||||||
|
|
||||||
|
@task
|
||||||
|
def test(project):
|
||||||
|
build = get_devops_build(project)
|
||||||
|
build.test()
|
9
infrastructure/docker-website-build/image/Dockerfile
Normal file
9
infrastructure/docker-website-build/image/Dockerfile
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
FROM clojure:temurin-18-jammy
|
||||||
|
|
||||||
|
# Prepare Entrypoint Script
|
||||||
|
ADD resources /tmp
|
||||||
|
|
||||||
|
ENV BUILDDIR="website"
|
||||||
|
|
||||||
|
RUN /tmp/install.sh
|
||||||
|
RUN /tmp/entrypoint.sh
|
15
infrastructure/docker-website-build/image/resources/entrypoint.sh
Executable file
15
infrastructure/docker-website-build/image/resources/entrypoint.sh
Executable file
|
@ -0,0 +1,15 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
source /usr/local/bin/functions.sh
|
||||||
|
|
||||||
|
function main() {
|
||||||
|
get-and-unzip-website-data
|
||||||
|
build-and-extract-website
|
||||||
|
move-website-files-to-target
|
||||||
|
}
|
||||||
|
|
||||||
|
main
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
sleep 1m
|
||||||
|
done
|
|
@ -0,0 +1,2 @@
|
||||||
|
.git
|
||||||
|
.gitignore
|
|
@ -0,0 +1,18 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# "Authorization: token YOURAUTHTOKEN"
|
||||||
|
function get-and-unzip-website-data() {
|
||||||
|
curl -H "$AUTHTOKEN" -O $REPOZIPURL # REPOZIPURL = https://your.gitea.host/api/v1/repos/<owner>/<repo>/archive/main.zip
|
||||||
|
mkdir $BUILDDIR
|
||||||
|
unzip main.zip -D $BUILDDIR
|
||||||
|
}
|
||||||
|
|
||||||
|
function build-and-extract-website() {
|
||||||
|
(cd $BUILDDIR; lein ring war; websiteartifactname=$(ls | grep -o *.war); unzip target/$websiteartifactname "WEB-INF/classes/public/*")
|
||||||
|
}
|
||||||
|
|
||||||
|
# set variables from environment
|
||||||
|
# read write zugriff sicherstellen
|
||||||
|
function move-website-files-to-target() {
|
||||||
|
rsync -ru --exclude-from "/home/$USER/exclude.pattern" --delete WEB-INF/classes/public/* $TARGETDIR # TARGETDIR = mount/path/to/website-content-vol with write permission
|
||||||
|
}
|
10
infrastructure/docker-website-build/image/resources/install.sh
Executable file
10
infrastructure/docker-website-build/image/resources/install.sh
Executable file
|
@ -0,0 +1,10 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
apt update > /dev/null;
|
||||||
|
|
||||||
|
install -m 0700 /tmp/entrypoint.sh /
|
||||||
|
|
||||||
|
install -m 0700 /tmp/functions.sh /usr/local/bin/
|
||||||
|
install -m 0700 /tmp/exclude.pattern /home/$USER
|
||||||
|
install -m 0700 /tmp/project.clj /home/$USER/.lein/
|
||||||
|
(cd /home/$USER/.lein; lein deps)
|
|
@ -0,0 +1,2 @@
|
||||||
|
{:user
|
||||||
|
{:plugins [[lein-ring "0.12.5"]]}}
|
11
infrastructure/docker-website-build/test/Dockerfile
Normal file
11
infrastructure/docker-website-build/test/Dockerfile
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
FROM c4k-jira-backup
|
||||||
|
|
||||||
|
RUN apt update
|
||||||
|
RUN apt -yqq --no-install-recommends --yes install curl default-jre-headless
|
||||||
|
|
||||||
|
RUN curl -L -o /tmp/serverspec.jar \
|
||||||
|
https://github.com/DomainDrivenArchitecture/dda-serverspec-crate/releases/download/2.0.0/dda-serverspec-standalone.jar
|
||||||
|
|
||||||
|
COPY serverspec.edn /tmp/serverspec.edn
|
||||||
|
|
||||||
|
RUN java -jar /tmp/serverspec.jar /tmp/serverspec.edn -v
|
5
infrastructure/docker-website-build/test/serverspec.edn
Normal file
5
infrastructure/docker-website-build/test/serverspec.edn
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{:file [{:path "/usr/local/bin/install.sh" :mod "700"}
|
||||||
|
{:path "/usr/local/bin/functions.sh" :mod "700"}
|
||||||
|
{:path "/usr/local/bin/exclude.pattern" :mod "700"}
|
||||||
|
{:path "/usr/local/bin/project.clj" :mod "700"}
|
||||||
|
{:path "/entrypoint.sh" :mod "700"}]}
|
16
shadow-cljs.edn
Normal file
16
shadow-cljs.edn
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
{:source-paths ["src/main/cljc"
|
||||||
|
"src/main/cljs"
|
||||||
|
"src/main/resources"
|
||||||
|
"src/test/cljc"
|
||||||
|
"src/test/cljs"
|
||||||
|
"src/test/resources"]
|
||||||
|
:dependencies [[org.domaindrivenarchitecture/c4k-common-cljs "3.0.1"]
|
||||||
|
[hickory "0.7.1"]
|
||||||
|
[org.clojure/math.numeric-tower "0.0.5"]]
|
||||||
|
:builds {:frontend {:target :browser
|
||||||
|
:modules {:main {:init-fn dda.c4k-website.browser/init}}
|
||||||
|
:release {}
|
||||||
|
:compiler-options {:optimizations :advanced}}
|
||||||
|
:test {:target :node-test
|
||||||
|
:output-to "target/node-tests.js"
|
||||||
|
:repl-pprint true}}}
|
|
@ -95,5 +95,7 @@ data:
|
||||||
root /var/www/html/website/;
|
root /var/www/html/website/;
|
||||||
# root /usr/share/nginx/html/; # testing purposes
|
# root /usr/share/nginx/html/; # testing purposes
|
||||||
index index.html;
|
index index.html;
|
||||||
try_files $uri /index.html;
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html =404;
|
||||||
|
}
|
||||||
}
|
}
|
47
src/main/resources/website/website-build-cron.yaml
Normal file
47
src/main/resources/website/website-build-cron.yaml
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
apiVersion: batch/v1beta1
|
||||||
|
kind: CronJob
|
||||||
|
metadata:
|
||||||
|
name: website-builder
|
||||||
|
labels:
|
||||||
|
app.kubernetes.part-of: website # correct name?
|
||||||
|
spec:
|
||||||
|
schedule: "10 23 * * *"
|
||||||
|
successfulJobsHistoryLimit: 1
|
||||||
|
failedJobsHistoryLimit: 1
|
||||||
|
jobTemplate:
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: backup-app
|
||||||
|
image: domaindrivenarchitecture/c4k-gitea-backup
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
command: ["/entrypoint.sh"]
|
||||||
|
env:
|
||||||
|
- name: AWS_DEFAULT_REGION
|
||||||
|
value: eu-central-1
|
||||||
|
- name: AWS_ACCESS_KEY_ID_FILE
|
||||||
|
value: /var/run/secrets/backup-secrets/aws-access-key-id
|
||||||
|
- name: AWS_SECRET_ACCESS_KEY_FILE
|
||||||
|
value: /var/run/secrets/backup-secrets/aws-secret-access-key
|
||||||
|
- name: RESTIC_REPOSITORY
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: backup-config
|
||||||
|
key: restic-repository
|
||||||
|
- name: RESTIC_PASSWORD_FILE
|
||||||
|
value: /var/run/secrets/backup-secrets/restic-password
|
||||||
|
volumeMounts:
|
||||||
|
- name: gitea-data-volume
|
||||||
|
mountPath: /var/backups
|
||||||
|
- name: backup-secret-volume
|
||||||
|
mountPath: /var/run/secrets/backup-secrets
|
||||||
|
readOnly: true
|
||||||
|
volumes:
|
||||||
|
- name: gitea-data-volume
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: gitea-data-pvc
|
||||||
|
- name: backup-secret-volume
|
||||||
|
secret:
|
||||||
|
secretName: backup-secret
|
||||||
|
restartPolicy: OnFailure
|
73
src/main/resources/website/website-build-deployment.yaml
Normal file
73
src/main/resources/website/website-build-deployment.yaml
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: backup-restore
|
||||||
|
spec:
|
||||||
|
replicas: 0
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: backup-restore
|
||||||
|
strategy:
|
||||||
|
type: Recreate
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: backup-restore
|
||||||
|
app.kubernetes.io/name: backup-restore
|
||||||
|
app.kubernetes.io/part-of: gitea
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: domaindrivenarchitecture/c4k-gitea-backup
|
||||||
|
name: backup-app
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
command: ["/entrypoint-start-and-wait.sh"]
|
||||||
|
env:
|
||||||
|
- name: POSTGRES_USER
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: postgres-secret
|
||||||
|
key: postgres-user
|
||||||
|
- name: POSTGRES_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: postgres-secret
|
||||||
|
key: postgres-password
|
||||||
|
- name: POSTGRES_DB
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: postgres-config
|
||||||
|
key: postgres-db
|
||||||
|
- name: POSTGRES_HOST
|
||||||
|
value: "postgresql-service:5432"
|
||||||
|
- name: POSTGRES_SERVICE
|
||||||
|
value: "postgresql-service"
|
||||||
|
- name: POSTGRES_PORT
|
||||||
|
value: "5432"
|
||||||
|
- name: AWS_DEFAULT_REGION
|
||||||
|
value: eu-central-1
|
||||||
|
- name: AWS_ACCESS_KEY_ID_FILE
|
||||||
|
value: /var/run/secrets/backup-secrets/aws-access-key-id
|
||||||
|
- name: AWS_SECRET_ACCESS_KEY_FILE
|
||||||
|
value: /var/run/secrets/backup-secrets/aws-secret-access-key
|
||||||
|
- name: RESTIC_REPOSITORY
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: backup-config
|
||||||
|
key: restic-repository
|
||||||
|
- name: RESTIC_PASSWORD_FILE
|
||||||
|
value: /var/run/secrets/backup-secrets/restic-password
|
||||||
|
- name: CERTIFICATE_FILE
|
||||||
|
value: ""
|
||||||
|
volumeMounts:
|
||||||
|
- name: gitea-data-volume
|
||||||
|
mountPath: /var/backups
|
||||||
|
- name: backup-secret-volume
|
||||||
|
mountPath: /var/run/secrets/backup-secrets
|
||||||
|
readOnly: true
|
||||||
|
volumes:
|
||||||
|
- name: gitea-data-volume
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: gitea-data-pvc
|
||||||
|
- name: backup-secret-volume
|
||||||
|
secret:
|
||||||
|
secretName: backup-secret
|
Loading…
Reference in a new issue