From ecb06edb1ef456baa0ad854a120a0218b30fae0a Mon Sep 17 00:00:00 2001 From: elf Pavlik Date: Tue, 3 Sep 2024 18:18:34 -0600 Subject: [PATCH] copy setup from docker-shared-services https://github.com/wayofdev/docker-shared-services --- .env | 79 ++++++ .gitignore | 2 + Makefile | 225 ++++++++++++++++++ docker-compose.yaml | 116 ++++++--- mkcert.sh | 60 +++++ .../setup/current-server-version$.json | 2 +- packages/css-storage-fixture/package.json | 2 +- packages/css-test-utils/package.json | 2 +- pnpm-lock.yaml | 14 +- traefik/certs/.gitignore | 1 + traefik/conf/traefik.yml | 48 ++++ 11 files changed, 505 insertions(+), 46 deletions(-) create mode 100644 .env create mode 100644 Makefile create mode 100755 mkcert.sh create mode 100644 traefik/certs/.gitignore create mode 100644 traefik/conf/traefik.yml diff --git a/.env b/.env new file mode 100644 index 00000000..9083f819 --- /dev/null +++ b/.env @@ -0,0 +1,79 @@ +# +# SS = Shared Services +# https://docs.docker.com/compose/reference/envvars/#compose_project_name +# +COMPOSE_PROJECT_NAME=sai + +# +# Domain, under which default, shared services will run. +# Default: .wod +# Example subdomains, under which services will run under: +# - pg-admin.wod.docker +# - router.wod.docker +# - ui.wod.docker +# Can be left blank, but then $TLS_DOMAINS need to contain all top level domains of your projects. +# +# Example: +# Using empty SHARED_DOMAIN_SEGMENT="" +# TLS_DOMAINS="pg-admin.docker router.docker ui.docker" +# Using custom SHARED_DOMAIN_SEGMENT=".wod" +# TLS_DOMAINS="pg-admin.wod.docker router.wod.docker ui.wod.docker" +# +SHARED_DOMAIN_SEGMENT= + +# +# Specify domains for mkcert +# Because of browser limitations, each top-level domain should be added separately. +# This ensures that certificates are correctly recognized by browsers. +# Examples of top-level domains: +# - pg-admin.docker +# - router.docker +# - ui.docker +# +# Wildcards can be used, but note that they only cover one level of subdomains. +# Example: +# - *.laravel-starter-tpl.docker will match api.laravel-starter-tpl.docker +# - However, it will not match api.prod.laravel-starter-tpl.docker +# +TLS_DOMAINS="router.docker pod.docker *.pod.docker sai.docker ui.sai.docker vuejectron.docker plenary.docker" + +# +# DNSMasq Configuration +# +# This service will route all *.docker domains to the local macOS or Linux machine. +# Example: your-project.docker will be routed to the local machine 127.0.0.1 +# +# `ping your-project.docker` will return +# +# PING your-project.docker (127.0.0.1): 56 data bytes +# 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.129 ms +# 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.173 ms +# 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.111 ms +# 64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.176 ms +# +# This allows further configuration of Traefik to route the traffic to the correct container. +# +# For more information, see: +# https://github.com/DrPsychick/docker-dnsmasq +# +# Note: To use, for example .mac domain, you need to change +# DMQ_GLOBAL=address=/docker/127.0.0.1 (to =>) DMQ_GLOBAL=address=/mac/127.0.0.1 +# +DMQ_DHCP_DNS=dhcp-option=6,172.17.10.1,8.8.8.8,8.8.4.4 +DMQ_DHCP_GATEWAY=dhcp-option=3,172.17.10.1 +DMQ_DHCP_PXE= +DMQ_DHCP_RANGES=dhcp-range=172.17.10.10,172.17.10.100,24h +DMQ_DHCP_TFTP= +DMQ_DHCP_WINS= +DMQ_DNS_ADDRESS= +DMQ_DNS_ALIAS= +DMQ_DNS_CNAME= +DMQ_DNS_DOMAIN=domain=local +DMQ_DNS_FLAGS=expand-hosts\ndomain-needed\nselfmx\ndns-loop-detect +DMQ_DNS_LOCAL=local=/local/ +DMQ_DNS_RESOLV=no-resolv +DMQ_DNS_SERVER=server=8.8.8.8\nserver=8.8.4.4 +DMQ_DNS_SRV= +DMQ_DNS_TXT= +#DMQ_GLOBAL=address=/docker/127.0.0.1 +DMQ_GLOBAL=address=/docker/172.100.61.250 diff --git a/.gitignore b/.gitignore index 70b5d711..68cbc268 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,5 @@ packages/css-storage-fixture/**/.internal/accounts/index/clientCredentials # ldo examples/*/ldo/ + +traefik/certs/* diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..147e33e3 --- /dev/null +++ b/Makefile @@ -0,0 +1,225 @@ +-include .env + +# BuildKit enables higher performance docker builds and caching possibility +# to decrease build times and increase productivity for free. +# https://docs.docker.com/compose/environment-variables/envvars/ +export DOCKER_BUILDKIT ?= 1 + +export CAROOT = $(shell mkcert -CAROOT) + +ifeq ($(COMPOSE_PROJECT_NAME),) + COMPOSE_PROJECT_NAME=ss +endif + +# Docker binary to use, when executing docker tasks +DOCKER ?= docker + +# Binary to use, when executing docker-compose tasks +DOCKER_COMPOSE ?= $(DOCKER) compose + +# Support image with all needed binaries, like envsubst, mkcert, wait4x +SUPPORT_IMAGE ?= wayofdev/build-deps:alpine-latest + +BUILDER_PARAMS ?= $(DOCKER) run --rm -i \ + --env-file ./.env \ + --env COMPOSE_PROJECT_NAME=$(COMPOSE_PROJECT_NAME) \ + --env SHARED_DOMAIN_SEGMENT="$(SHARED_DOMAIN_SEGMENT)" + +BUILDER ?= $(BUILDER_PARAMS) $(SUPPORT_IMAGE) +BUILDER_WIRED ?= $(BUILDER_PARAMS) --network network.$(COMPOSE_PROJECT_NAME) $(SUPPORT_IMAGE) + +# Shorthand envsubst command, executed through build-deps +ENVSUBST ?= $(BUILDER) envsubst + +# Yamllint docker image +YAML_LINT_RUNNER ?= $(DOCKER) run --rm $$(tty -s && echo "-it" || echo) \ + -v $(PWD):/data \ + cytopia/yamllint:latest \ + -c ./.github/.yamllint.yaml \ + -f colored . + +ACTION_LINT_RUNNER ?= $(DOCKER) run --rm $$(tty -s && echo "-it" || echo) \ + -v $(shell pwd):/repo \ + --workdir /repo \ + rhysd/actionlint:latest \ + -color + +MARKDOWN_LINT_RUNNER ?= $(DOCKER) run --rm $$(tty -s && echo "-it" || echo) \ + -v $(shell pwd):/app \ + --workdir /app \ + davidanson/markdownlint-cli2-rules:latest \ + --config ".github/.markdownlint.json" + +EXPORT_VARS = '\ + $${SHARED_DOMAIN_SEGMENT} \ + $${COMPOSE_PROJECT_NAME}' + +# +# Self documenting Makefile code +# ------------------------------------------------------------------------------------ +ifneq ($(TERM),) + BLACK := $(shell tput setaf 0) + RED := $(shell tput setaf 1) + GREEN := $(shell tput setaf 2) + YELLOW := $(shell tput setaf 3) + LIGHTPURPLE := $(shell tput setaf 4) + PURPLE := $(shell tput setaf 5) + BLUE := $(shell tput setaf 6) + WHITE := $(shell tput setaf 7) + RST := $(shell tput sgr0) +else + BLACK := "" + RED := "" + GREEN := "" + YELLOW := "" + LIGHTPURPLE := "" + PURPLE := "" + BLUE := "" + WHITE := "" + RST := "" +endif +MAKE_LOGFILE = /tmp/wayofdev-docker-shared-services.log +MAKE_CMD_COLOR := $(BLUE) + +default: all + +help: + @echo 'Management commands for project:' + @echo 'Usage:' + @echo ' ${MAKE_CMD_COLOR}make${RST} Creates containers, spins up project' + @grep -E '^[a-zA-Z_0-9%-]+:.*?## .*$$' Makefile | awk 'BEGIN {FS = ":.*?## "}; {printf " ${MAKE_CMD_COLOR}make %-21s${RST} %s\n", $$1, $$2}' + @echo + @echo ' 📑 Logs are stored in $(MAKE_LOGFILE)' + @echo + @echo ' 📦 Package docker-shared-services (https://github.com/wayofdev/docker-shared-services)' + @echo ' 🤠 Author Andrij Orlenko (https://github.com/lotyp)' + @echo ' 🏢 ${YELLOW}Org wayofdev (https://github.com/wayofdev)${RST}' + @echo +.PHONY: help + +.EXPORT_ALL_VARIABLES: + +# +# Default action +# Defines default command when `make` is executed without additional parameters +# ------------------------------------------------------------------------------------ +all: hooks env up +PHONY: all + +# +# System Actions +# ------------------------------------------------------------------------------------ +env: ## Generate .env file from example, use `make env force=true`, to force re-create file +ifeq ($(FORCE),true) + @echo "${YELLOW}Force re-creating .env file from example...${RST}" + @# $(ENVSUBST) $(EXPORT_VARS) < ./.env.example > ./.env + cp ./.env.example ./.env +else ifneq ("$(wildcard ./.env)","") + @echo "" + @echo "${YELLOW}The .env file already exists! Use FORCE=true to re-create.${RST}" +else + @echo "Creating .env file from example" + @# $(ENVSUBST) $(EXPORT_VARS) < ./.env.example > ./.env + cp ./.env.example ./.env +endif +.PHONY: env + +override-create: ## Generate override file from dist + cp -v docker-compose.override.yaml.dist docker-compose.override.yaml +.PHONY: override-create + +cert-install: ## Run mkcert to install CA into system storage and generate default certs for traefik + bash mkcert.sh +.PHONY: cert-install + +# +# Docker Actions +# ------------------------------------------------------------------------------------ +up: ## Fire up project + $(DOCKER_COMPOSE) up --remove-orphans -d --wait +.PHONY: up + +up-router: ## Start only traefik service + $(DOCKER_COMPOSE) up --remove-orphans -d --no-deps router --wait +.PHONY: up-router + +up-dns: ## Start only dns service + $(DOCKER_COMPOSE) up --remove-orphans -d --no-deps dns --wait +.PHONY: up-dns + +down: ## Stops and destroys running containers + $(DOCKER_COMPOSE) down --remove-orphans +.PHONY: down + +stop: ## Stops all containers, without removing them + $(DOCKER_COMPOSE) stop +.PHONY: stop + +restart: down up ## Restart all containers, running in this project +.PHONY: restart + +logs: ## Show logs for running containers in this project + $(DOCKER_COMPOSE) logs -f +.PHONY: logs + +ps: ## List running containers in this project + $(DOCKER_COMPOSE) ps +.PHONY: ps + +pull: ## Pull upstream images, specified in docker-compose.yml file + $(DOCKER_COMPOSE) pull +.PHONY: pull + +clean: + $(DOCKER_COMPOSE) rm --force --stop +.PHONY: clean + +prune: ## Stops and removes all containers and volumes + $(DOCKER_COMPOSE) down --remove-orphans --volumes +.PHONY: prune + +# +# Code Quality, Git, Linting +# ------------------------------------------------------------------------------------ +hooks: ## Install git hooks from pre-commit-config + pre-commit install + pre-commit install --hook-type commit-msg + pre-commit autoupdate +.PHONY: hooks + +lint: lint-yaml lint-actions lint-md ## Lint all files in project +.PHONY: lint + +lint-yaml: ## Lints yaml files inside project + @$(YAML_LINT_RUNNER) | tee -a $(MAKE_LOGFILE) +.PHONY: lint-yaml + +lint-actions: ## Lint all github actions + @$(ACTION_LINT_RUNNER) | tee -a $(MAKE_LOGFILE) +.PHONY: lint-actions + +lint-md: ## Lint all markdown files using markdownlint-cli2 + @$(MARKDOWN_LINT_RUNNER) --fix "**/*.md" "!CHANGELOG.md" | tee -a $(MAKE_LOGFILE) +.PHONY: lint-md + +lint-md-dry: ## Lint all markdown files using markdownlint-cli2 in dry-run mode + @$(MARKDOWN_LINT_RUNNER) "**/*.md" "!CHANGELOG.md" | tee -a $(MAKE_LOGFILE) +.PHONY: lint-md-dry + +# +# Testing +# ------------------------------------------------------------------------------------ +# dcgoss binary is used for testing +# README: https://github.com/aelsabbahy/goss/tree/master/extras/dcgoss +# macOS install: https://github.com/goss-org/goss/tree/master/extras/dgoss#mac-osx +# +test: ## Run self-tests using dcgoss + dcgoss run router +.PHONY: test + +# +# Release +# ------------------------------------------------------------------------------------ +commit: ## Run commitizen to create commit message + czg commit --config="./.github/.cz.config.js" +.PHONY: commit diff --git a/docker-compose.yaml b/docker-compose.yaml index e533f025..52c8eeb2 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -4,13 +4,11 @@ services: restart: on-failure networks: - default - - shared sai: image: node:22-alpine restart: on-failure networks: - default - - shared expose: - 4000 ports: @@ -40,40 +38,38 @@ services: - traefik.http.routers.sai.tls=true - traefik.http.services.sai.loadbalancer.server.port=4000 - traefik.http.middlewares.testheader.headers.customrequestheaders.X-Forwarded-Proto=https - # css: - # image: node:22-alpine - # restart: on-failure - # networks: - # - default - # - shared - # dns: - # - 172.100.61.253 - # expose: - # - 3000 - # working_dir: /sai/packages/css-storage-fixture - # command: ["npm", "run", "dev"] - # volumes: - # - ./:/sai - # - ${CAROOT}:/mkcert - # environment: - # - CSS_CONFIG=/sai/packages/css-storage-fixture/config.json - # - CSS_LOGGING_LEVEL=info - # - CSS_ROOT_FILE_PATH=/sai/packages/css-storage-fixture/dev - # - CSS_BASE_URL=https://pod.docker - # - NODE_EXTRA_CA_CERTS=/mkcert/rootCA.pem - # labels: - # - traefik.enable=true - # - traefik.http.routers.pod.rule=Host(`pod.docker`) || HostRegexp(`^.+\.pod\.docker$`) - # - traefik.http.routers.pod.entrypoints=websecure - # - traefik.http.routers.pod.tls=true - # - traefik.http.services.pod.loadbalancer.server.port=3000 - # - traefik.http.middlewares.testheader.headers.customrequestheaders.X-Forwarded-Proto=https + css: + image: node:22-alpine + restart: on-failure + networks: + - default + dns: + - 172.100.61.253 + expose: + - 3000 + working_dir: /sai/packages/css-storage-fixture + command: ["npm", "run", "dev"] + volumes: + - ./:/sai + - ${CAROOT}:/mkcert + environment: + - CSS_CONFIG=/sai/packages/css-storage-fixture/config.json + - CSS_LOGGING_LEVEL=info + - CSS_ROOT_FILE_PATH=/sai/packages/css-storage-fixture/dev + - CSS_BASE_URL=https://pod.docker + - NODE_EXTRA_CA_CERTS=/mkcert/rootCA.pem + labels: + - traefik.enable=true + - traefik.http.routers.pod.rule=Host(`pod.docker`) || HostRegexp(`^.+\.pod\.docker$`) + - traefik.http.routers.pod.entrypoints=websecure + - traefik.http.routers.pod.tls=true + - traefik.http.services.pod.loadbalancer.server.port=3000 + - traefik.http.middlewares.testheader.headers.customrequestheaders.X-Forwarded-Proto=https ui: image: node:22-alpine restart: on-failure networks: - default - - shared expose: - 4200 working_dir: /sai/ui/authorization @@ -91,7 +87,6 @@ services: restart: on-failure networks: - default - - shared expose: - 4500 working_dir: /sai/examples/vuejectron @@ -105,9 +100,58 @@ services: - traefik.http.routers.vuejectron.tls=true - traefik.http.services.vuejectron.loadbalancer.server.port=4500 + router: + image: traefik:v3.0.4 + container_name: router + restart: on-failure + ports: + - '80:80' + - '443:443' + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - ./traefik/conf/traefik.yml:/etc/traefik/traefik.yml + - ./traefik/certs/cert.pem:/etc/traefik/cert.pem + - ./traefik/certs/key.pem:/etc/traefik/key.pem + labels: + - traefik.enable=true + - traefik.http.routers.router.rule=Host(`router${SHARED_DOMAIN_SEGMENT}.docker`) + - traefik.http.routers.router.entrypoints=websecure + - traefik.http.services.router.loadbalancer.server.port=8080 + - traefik.http.routers.router.tls=true + healthcheck: + test: ['CMD-SHELL', 'traefik healthcheck --ping'] + interval: 4s + timeout: 4s + retries: 8 + start_period: 4s + networks: + default: + ipv4_address: 172.100.61.250 + + dns: + image: drpsychick/dnsmasq:latest + container_name: dnsmasq + restart: unless-stopped + env_file: + - .env + ports: + - '53:53/tcp' + - '53:53/udp' + cap_add: + - NET_ADMIN + healthcheck: + test: ['CMD-SHELL', 'nslookup localhost 127.0.0.1 || exit 1'] + interval: 4s + timeout: 4s + retries: 8 + start_period: 4s + networks: + default: + ipv4_address: 172.100.61.253 + networks: - shared: - external: true - name: network.ss default: - name: network.sai + name: network.${COMPOSE_PROJECT_NAME} + ipam: + config: + - subnet: 172.100.61.0/24 diff --git a/mkcert.sh b/mkcert.sh new file mode 100755 index 00000000..0265b744 --- /dev/null +++ b/mkcert.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash + +# Function to check if mkcert is installed +check_mkcert_installed() { + if ! command -v mkcert &> /dev/null; then + echo "[Error] mkcert is not installed. Please install mkcert first." + exit 1 + fi +} + +# Function to install mkcert CA +install_mkcert_ca() { + echo "[Info] Installing mkcert CA..." + mkcert -install +} + +# Function to load environment variables from .env file +load_env() { + if [ ! -f .env ]; then + echo "[Warning] .env file not found. Please generate it using make env command!" + exit 1 + else + set -a + # shellcheck disable=SC2002 + source <(cat .env | sed -e '/^#/d;/^\s*$/d' -e "s/'/'\\\''/g" -e "s/=\(.*\)/='\1'/g") + set +a + fi +} + +# Function to display domains to be loaded +display_domains() { + local DOMAINS + local DOMAIN + + DOMAINS=$(echo "$TLS_DOMAINS" | sed -e 's/^"//' -e 's/"$//') + + echo "[Info] Domains to load:" + for DOMAIN in $DOMAINS; do + echo " - ${DOMAIN}" + done +} + +# Function to generate certificates +generate_certs() { + local DOMAINS + DOMAINS=$(echo "$TLS_DOMAINS" | sed -e 's/^"//' -e 's/"$//') + # shellcheck disable=SC2086 + mkcert -key-file traefik/certs/key.pem -cert-file traefik/certs/cert.pem $DOMAINS +} + +# Main script execution +main() { + check_mkcert_installed + install_mkcert_ca + load_env + display_domains + generate_certs +} + +main diff --git a/packages/css-storage-fixture/dev/www/.internal/setup/current-server-version$.json b/packages/css-storage-fixture/dev/www/.internal/setup/current-server-version$.json index be982107..381953c1 100644 --- a/packages/css-storage-fixture/dev/www/.internal/setup/current-server-version$.json +++ b/packages/css-storage-fixture/dev/www/.internal/setup/current-server-version$.json @@ -1 +1 @@ -{"key":"setup/current-server-version","payload":"7.1.1"} \ No newline at end of file +{"key":"setup/current-server-version","payload":"7.1.2"} \ No newline at end of file diff --git a/packages/css-storage-fixture/package.json b/packages/css-storage-fixture/package.json index 607a67c5..6c0bc9e6 100644 --- a/packages/css-storage-fixture/package.json +++ b/packages/css-storage-fixture/package.json @@ -15,6 +15,6 @@ "author": "", "license": "MIT", "dependencies": { - "@solid/community-server": "^7.1.1" + "@solid/community-server": "^7.1.2" } } diff --git a/packages/css-test-utils/package.json b/packages/css-test-utils/package.json index d20e2c23..23c12702 100644 --- a/packages/css-test-utils/package.json +++ b/packages/css-test-utils/package.json @@ -34,7 +34,7 @@ }, "dependencies": { "@inrupt/solid-client-authn-core": "^2.0.0", - "@solid/community-server": "^7.1.1", + "@solid/community-server": "^7.1.2", "n3": "^1.17.1" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 02a0dab3..47a3468f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -303,8 +303,8 @@ importers: packages/css-storage-fixture: dependencies: '@solid/community-server': - specifier: ^7.1.1 - version: 7.1.1 + specifier: ^7.1.2 + version: 7.1.2 packages/css-test-utils: dependencies: @@ -312,8 +312,8 @@ importers: specifier: ^2.0.0 version: 2.0.0 '@solid/community-server': - specifier: ^7.1.1 - version: 7.1.1 + specifier: ^7.1.2 + version: 7.1.2 n3: specifier: ^1.17.1 version: 1.17.2 @@ -2651,8 +2651,8 @@ packages: '@solid/access-token-verifier@2.1.0': resolution: {integrity: sha512-79u92GD1SBTxjYghg2ta6cfoBNZ5ljz/9zE6RmXUypTXW7oI18DTWiSrEjWwI4njW+OMh+4ih+sAR6AkI1IFxg==} - '@solid/community-server@7.1.1': - resolution: {integrity: sha512-C551rfeQHkrY7qC+YbawYFMv6Vfifui2//vwZrxUNyQ1j/IZVfqzaj06R+UpqmajVxRsXTf/XtSjb+3lpTCyeg==} + '@solid/community-server@7.1.2': + resolution: {integrity: sha512-VLCr8EoL4/aeQUag1Dv0pSPkl5lJ7y6igmc0UHYEwIT4tRE8OxRaD2A6C+BmF93J4G1za9IT32eCUh+uPJD3uw==} engines: {node: '>=18.0'} hasBin: true @@ -9973,7 +9973,7 @@ snapshots: transitivePeerDependencies: - encoding - '@solid/community-server@7.1.1': + '@solid/community-server@7.1.2': dependencies: '@comunica/context-entries': 2.8.2 '@comunica/query-sparql': 2.9.0 diff --git a/traefik/certs/.gitignore b/traefik/certs/.gitignore new file mode 100644 index 00000000..f935021a --- /dev/null +++ b/traefik/certs/.gitignore @@ -0,0 +1 @@ +!.gitignore diff --git a/traefik/conf/traefik.yml b/traefik/conf/traefik.yml new file mode 100644 index 00000000..277102f8 --- /dev/null +++ b/traefik/conf/traefik.yml @@ -0,0 +1,48 @@ +--- + +global: + sendAnonymousUsage: false + +providers: + docker: + exposedByDefault: false + network: network.ss + file: + directory: /etc/traefik + watch: true + +api: + insecure: true + +serversTransport: + insecureSkipVerify: true + +entryPoints: + web: + address: ':80' + http: + redirections: + entryPoint: + to: websecure + scheme: https + + websecure: + address: ':443' + +tls: + certificates: + - certFile: /etc/traefik/cert.pem + keyFile: /etc/traefik/key.pem + stores: + default: + defaultCertificate: + certFile: /etc/traefik/cert.pem + keyFile: /etc/traefik/key.pem + +ping: + entryPoint: 'web' + +log: + level: DEBUG + +...