From 00eb6987c6777f4b5d7161135560021deab0a486 Mon Sep 17 00:00:00 2001 From: Leonard Jonathan Oh Date: Tue, 31 Oct 2023 14:58:42 +0000 Subject: [PATCH] Enhancement (ci): Add `traefik` as web reverse proxy in `docker-compose.example.yml` and add test --- .github/workflows/ci-master-pr.yml | 19 ++++---- README.md | 10 ++++- docker-compose.example.yml | 72 ++++++++++++++++++++++++++++-- docker-compose.test.yml | 31 +++++++++++++ 4 files changed, 119 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci-master-pr.yml b/.github/workflows/ci-master-pr.yml index 6abb8ccd..af4570ed 100644 --- a/.github/workflows/ci-master-pr.yml +++ b/.github/workflows/ci-master-pr.yml @@ -48,15 +48,18 @@ jobs: docker buildx ls docker compose version - - name: Test (integration) + - name: Integration test (dev) + if: matrix.testenv == 'dev' run: | - set -eu - if [ "${{ matrix.testenv }}" == 'dev' ]; then - docker compose up --build -d - fi - if [ "${{ matrix.testenv }}" == 'prod' ]; then - docker compose -f docker-compose.example.yml -f docker-compose.example.build.yml up --build -d - fi + set -eux + docker compose up --build -d + docker compose -f docker-compose.test.yml up test-routes + + - name: Integration test (prod) + if: matrix.testenv == 'prod' + run: | + set -eux + docker compose -f docker-compose.example.yml -f docker-compose.example.build.yml up --build -d docker compose -f docker-compose.test.yml up build: diff --git a/README.md b/README.md index 3061ecb8..8fb6a1fc 100644 --- a/README.md +++ b/README.md @@ -56,9 +56,16 @@ To deploy using Docker Compose: ```sh docker compose -f docker-compose.example.yml up +# `web` is available at http://localhost:8081 or https://web.example.com +# `phpmyadmin` is available at http://localhost:8083 or https://phpmyadmin.example.com + +# You may need to add these DNS records in the hosts file +echo '127.0.0.1 web.example.com' | sudo tee -a /etc/hosts +echo '127.0.0.1 phpmyadmin.example.com' | sudo tee -a /etc/hosts ``` - [install.sql](./sql/install.sql) is mounted in `mysql` container which automatically installs the DB only on the first time. If you prefer not to mount `install.sql`, you may manually install the DB by logging into PHPMyAdmin and importing the `install.sql` there. +- `traefik` serves HTTPS with a self-signed cert. All HTTP requests are redirected to HTTPS. ### Upgrading (docker) @@ -126,10 +133,11 @@ docker exec -it $( docker compose ps -q heatmaps) php /heatmaps/generate.php #-- docker exec -it $( docker compose ps -q db ) sh # Test routes -docker compose -f docker-compose.test.yml up +docker compose -f docker-compose.test.yml up test-routes # Test production builds locally docker compose -f docker-compose.example.yml -f docker-compose.example.build.yml up --build +docker compose -f docker-compose.test.yml up # Dump the DB docker exec $( docker compose ps -q db ) mysqldump -uroot -proot hlstatsxce | gzip > hlstatsxce.sql.gz diff --git a/docker-compose.example.yml b/docker-compose.example.yml index 7cd63f5f..d27644c2 100644 --- a/docker-compose.example.yml +++ b/docker-compose.example.yml @@ -119,10 +119,24 @@ services: - default # 5. HLStatsX:CE web - # Available at http://localhost:8081 + # Available at http://localhost:8081, or https://web.example.com # Admin Panel username: admin, password: 123456 web: image: startersclan/hlstatsx-community-edition:1.8.0-web + labels: + - "traefik.enable=true" + - "traefik.docker.network=hlstatsx-community-edition_traefik-network" + # traefik v2 + # http + - "traefik.http.routers.hlstatsx-community-edition-web-http.entrypoints=web" + - "traefik.http.routers.hlstatsx-community-edition-web-http.rule=Host(`web.example.com`)" + - "traefik.http.routers.hlstatsx-community-edition-web-http.middlewares=hlstatsx-community-edition-web-http-myRedirectScheme" # Redirect http to https + - "traefik.http.middlewares.hlstatsx-community-edition-web-http-myRedirectScheme.redirectScheme.scheme=https" # Redirect http to https + # https + - "traefik.http.routers.hlstatsx-community-edition-web.entrypoints=websecure" + - "traefik.http.routers.hlstatsx-community-edition-web.tls=" + - "traefik.http.routers.hlstatsx-community-edition-web.rule=Host(`web.example.com`)" + - "traefik.http.services.hlstatsx-community-edition-web.loadbalancer.server.port=80" volumes: - games-volume:/web/hlstatsimg/games # Stateful games volume, which also contains heatmaps environment: @@ -132,9 +146,10 @@ services: - DB_PASS=hlstatsxce - DB_DEBUG=0 ports: - - 8081:80 + - 127.0.0.1:8081:80 - 9000 networks: + - traefik-network - default depends_on: - init-container @@ -175,14 +190,29 @@ services: exec crond -f # PHPMyAdmin to manage DB - # Available at http://localhost:8083 + # Available at http://localhost:8083, or https://phpmyadmin.example.com phpmyadmin: image: phpmyadmin:5.2 + labels: + - "traefik.enable=true" + - "traefik.docker.network=hlstatsx-community-edition_traefik-network" + # traefik v2 + # http + - "traefik.http.routers.hlstatsx-community-edition-phpmyadmin-http.entrypoints=web" + - "traefik.http.routers.hlstatsx-community-edition-phpmyadmin-http.rule=Host(`phpmyadmin.example.com`)" + - "traefik.http.routers.hlstatsx-community-edition-phpmyadmin-http.middlewares=hlstatsx-community-edition-phpmyadmin-http-myRedirectScheme" # Redirect http to https + - "traefik.http.middlewares.hlstatsx-community-edition-phpmyadmin-http-myRedirectScheme.redirectScheme.scheme=https" # Redirect http to https + # https + - "traefik.http.routers.hlstatsx-community-edition-phpmyadmin.entrypoints=websecure" + - "traefik.http.routers.hlstatsx-community-edition-phpmyadmin.tls=" + - "traefik.http.routers.hlstatsx-community-edition-phpmyadmin.rule=Host(`phpmyadmin.example.com`)" + - "traefik.http.services.hlstatsx-community-edition-phpmyadmin.loadbalancer.server.port=80" environment: - PMA_HOST=db ports: - - 8083:80 + - 127.0.0.1:8083:80 networks: + - traefik-network - default # Init container to set permissions in mounted folders and volumes @@ -202,10 +232,44 @@ services: echo "Granting db write permissions" chown -R 999:999 /var/lib/mysql + # The reverse proxy for our web containers + # See https://github.com/traefik/traefik/tree/v2.7/docs/content/user-guides/docker-compose for some examples for enabling HTTPS using ACME + # You will need a domain name. E.g. 'example.com' + traefik: + image: traefik:v2.10 + volumes: + # Allow traefik to listen to the Docker events + - /var/run/docker.sock:/var/run/docker.sock:ro + - traefik-acme-volume:/letsencrypt + ports: + - 80:80 + - 443:443 + networks: + - traefik-public-network + - traefik-network + restart: unless-stopped + command: + - --global.checknewversion=false + - --global.sendanonymoususage=false + # - --log.level=DEBUG + - --providers.docker=true + - --providers.docker.exposedbydefault=false + - --entrypoints.web.address=:80 + - --entrypoints.websecure.address=:443 + - --certificatesresolvers.myresolver.acme.dnschallenge=true + - --certificatesresolvers.myresolver.acme.dnschallenge.provider=ovh + # - --certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory + - --certificatesresolvers.myresolver.acme.email=postmaster@example.com + - --certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json + networks: default: + traefik-public-network: + traefik-network: + internal: true volumes: dns-volume: db-volume: games-volume: + traefik-acme-volume: diff --git a/docker-compose.test.yml b/docker-compose.test.yml index d85fbbe9..fa8518af 100644 --- a/docker-compose.test.yml +++ b/docker-compose.test.yml @@ -23,6 +23,7 @@ services: http://web/trend_graph.php 200 networks: - default + stop_signal: SIGKILL entrypoint: - /bin/sh command: @@ -54,5 +55,35 @@ services: fi done + test-endpoints: + build: + dockerfile_inline: | + FROM alpine:latest + RUN apk add --no-cache curl + environment: + ENDPOINTS: | + web.example.com 200 + phpmyadmin.example.com 200 + network_mode: host + depends_on: + test-routes: + condition: service_completed_successfully + stop_signal: SIGKILL + entrypoint: + - /bin/sh + command: + - -c + - | + set -eu + + echo "$$ENDPOINTS" | awk NF | while read -r i j; do + if curl --head -kL http://$$i --resolve $$i:80:127.0.0.1 --resolve $$i:443:127.0.0.1 2>&1 | grep "^HTTP/2 $$j " > /dev/null; then + echo "PASS: $$i" + else + echo "FAIL: $$i" + exit 1 + fi + done + networks: default: