diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2888fad..af6563c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -88,7 +88,7 @@ jobs: uses: docker/build-push-action@v2 with: context: . - file: Dockerfile + file: build/Dockerfile build-args: | RELEASE_VERSION_ARG="${{ join(steps.tags.outputs.result, ',') }}" platforms: linux/amd64,linux/arm64 diff --git a/Makefile b/Makefile index 4c3b4e4..0b7e07f 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ VERSION := $(shell git rev-parse --short HEAD) .PHONY: build build: - docker build -t byjg/easy-haproxy --build-arg RELEASE_VERSION_ARG="$(VERSION)" -t byjg/easy-haproxy:local . + docker build -t byjg/easy-haproxy --build-arg RELEASE_VERSION_ARG="$(VERSION)" -t byjg/easy-haproxy:local -f build/Dockerfile . .PHONY: test test: diff --git a/README.md b/README.md index 1ddb82f..f00af27 100644 --- a/README.md +++ b/README.md @@ -12,13 +12,15 @@ This Docker image will dynamically create the `haproxy.cfg` based on the labels a simple Yaml. EasyHAProxy can detect and configure automatically HAProxy on the folowing platforms: + - Docker - Docker Swarm - Kubernetes ## Features -EasyHAProxy will discover the services based on the Docker Tags of the running containers in a Docker host or Docker Swarm cluster and dynamically set up the `haproxy.cfg`. Below, EasyHAProxy main features:: +EasyHAProxy will discover the services based on the Docker Tags of the running containers in a Docker host or Docker Swarm cluster and dynamically set up the `haproxy.cfg`. Below, EasyHAProxy main features: + - Use Letsencrypt with HAProxy. - Set your custom SSL certificates - Balance traffic between multiple replicas @@ -113,6 +115,7 @@ Important: easyhaproxy needs to be in the same network of the containers or othe This will query all `ingress` in the kubernetes cluster and check the annotation `kubernetes.io/ingress.class: easyhaproxy-ingress`. e.g.: + ```yaml kind: Ingress metadata: @@ -150,7 +153,7 @@ Caveats: - Only the first path `spec.rules[].http.paths[0]` will be parsed. - There are specific annotations can be added as described bellow. -### Kubernetes annotations: +### Kubernetes annotations | annotation | Description | Default | Example | |-----------------------------|-----------------------------------------------------------------------------------------|--------------|--------------| @@ -180,7 +183,7 @@ spec: Make sure your cluster is accessible both through ports 80 and 443. -### Kubernetes and SSL: +### Kubernetes and SSL You need to create a secret with your certificate and key, and associate them in your ingress. @@ -213,7 +216,7 @@ spec: ... ``` -### Container (Docker or Swarm) labels: +### Container (Docker or Swarm) labels | Tag | Description | Default | Example | |---------------------------------------|-------------------------------------------------------------------------------------------------------|----------------|--------------| @@ -387,6 +390,7 @@ docker run \ ``` Run your container: + ```bash docker run \ -l easyhaproxy.express.port=80 \ @@ -401,15 +405,15 @@ Caveats: - Your container **must** listen to the port 80. Besides no error, the certificate won't be issued if in a different port. - The port 2080 is reserved for the certbot and should not be exposed. -- You cannot set the port 443 for the container with the Letsencrypt because EasyHAProxy will handle this automatically once the certificate is issued. +- You cannot set the port 443 for the container with the Letsencrypt because EasyHAProxy will handle this automatically once the certificate is issued. - If you don't run the EasyHAProxy with the parameter `EASYHAPROXY_LETSENCRYPT_EMAIL` no certificate will be issued. - Be aware of Letsencrypt issue limits - https://letsencrypt.org/docs/duplicate-certificate-limit/ and https://letsencrypt.org/docs/rate-limits/ ## Exposing Ports -You must expose some ports on the EasyHAProxy container and in the firewall. However, you don't need to expose the other container ports because EasyHAProxy will handle that. +You must expose some ports on the EasyHAProxy container and in the firewall. However, you don't need to expose the other container ports because EasyHAProxy will handle that. -- The ports `80` and `443`. +- The ports `80` and `443`. - If you enable the HAProxy statistics, you must also expose the port defined in `HAPROXY_STATS_PORT` environment variable (default 1936). Be aware that statististics are enabled by default with no password. - Every port defined in `easyhaproxy.[definitions].port` also should be exposed. @@ -424,7 +428,6 @@ docker run \ -d byjg/easy-haproxy ``` - ## Mapping custom .cfg files You can concatenate valid HAProxy `.cfg` files to the dynamically generated `haproxy.cfg` by mapping the folder `/etc/haproxy/conf.d`. @@ -438,7 +441,8 @@ docker run \ ## Mapping SSL certificates volumes -EasyHAProxy stores the certificates inside the folder `/certs/haproxy` and `/certs/letsencrypt`. +EasyHAProxy stores the certificates inside the folder `/certs/haproxy` and `/certs/letsencrypt`. + - If you want to preserve the letsencrypt certificates between reloads, map the folder `/certs/letsencrypt` to your volume. - If you want to provide your certificates as a file instead of a Base64 parameter, map the folder `/certs/haproxy` to your volume, and instead of use `easyhaproxy.[definition].sslcert`, use `easyhaproxy.[definition].ssl: true` @@ -486,14 +490,14 @@ where ERROR_NUMBER is the HTTP error code (e.g., `503.http`) ## Build - ```bash docker build -t byjg/easy-haproxy . ``` ## Limitations -EasyHAProxy has some limitations when there is more than one easy-haproxy container running: +EasyHAProxy has some limitations when there is more than one easy-haproxy container running: + - Replicas can be out-of-sync for a few seconds because each replica will discover the pods separately. - Each replica will request a Letsencrypt certificate and can fail because the letsencrypt challenge can be directed to the other replica. diff --git a/build-multiarch.sh b/build-multiarch.sh index a2fe1bb..716412b 100755 --- a/build-multiarch.sh +++ b/build-multiarch.sh @@ -17,7 +17,7 @@ podman run --rm --events-backend=file --cgroup-manager=cgroupfs --privileged doc for VERSION in $VERSIONS do - DOCKERFILE=Dockerfile + DOCKERFILE=build/Dockerfile buildah manifest create byjg/easy-haproxy:$VERSION @@ -29,4 +29,3 @@ do buildah manifest push --all --format v2s2 byjg/easy-haproxy:$VERSION docker://byjg/easy-haproxy:$VERSION done - diff --git a/Dockerfile b/build/Dockerfile similarity index 96% rename from Dockerfile rename to build/Dockerfile index c252af6..20c3459 100644 --- a/Dockerfile +++ b/build/Dockerfile @@ -8,7 +8,7 @@ ENV TZ="Etc/UTC" WORKDIR /scripts COPY src/ /scripts/ -COPY assets / +COPY build/assets / RUN apk add --no-cache haproxy bash python3 py3-pip py-yaml certbot openssl \ && ln -s /usr/bin/python3 /usr/bin/python \ diff --git a/assets/certs/haproxy/.place_holder_cert.pem b/build/assets/certs/haproxy/.place_holder_cert.pem similarity index 100% rename from assets/certs/haproxy/.place_holder_cert.pem rename to build/assets/certs/haproxy/.place_holder_cert.pem diff --git a/assets/etc/haproxy/conf.d/README.md b/build/assets/etc/haproxy/conf.d/README.md similarity index 100% rename from assets/etc/haproxy/conf.d/README.md rename to build/assets/etc/haproxy/conf.d/README.md diff --git a/assets/etc/haproxy/errors-custom/400.http b/build/assets/etc/haproxy/errors-custom/400.http similarity index 100% rename from assets/etc/haproxy/errors-custom/400.http rename to build/assets/etc/haproxy/errors-custom/400.http diff --git a/assets/etc/haproxy/errors-custom/403.http b/build/assets/etc/haproxy/errors-custom/403.http similarity index 100% rename from assets/etc/haproxy/errors-custom/403.http rename to build/assets/etc/haproxy/errors-custom/403.http diff --git a/assets/etc/haproxy/errors-custom/408.http b/build/assets/etc/haproxy/errors-custom/408.http similarity index 100% rename from assets/etc/haproxy/errors-custom/408.http rename to build/assets/etc/haproxy/errors-custom/408.http diff --git a/assets/etc/haproxy/errors-custom/500.http b/build/assets/etc/haproxy/errors-custom/500.http similarity index 100% rename from assets/etc/haproxy/errors-custom/500.http rename to build/assets/etc/haproxy/errors-custom/500.http diff --git a/assets/etc/haproxy/errors-custom/502.http b/build/assets/etc/haproxy/errors-custom/502.http similarity index 100% rename from assets/etc/haproxy/errors-custom/502.http rename to build/assets/etc/haproxy/errors-custom/502.http diff --git a/assets/etc/haproxy/errors-custom/503.http b/build/assets/etc/haproxy/errors-custom/503.http similarity index 100% rename from assets/etc/haproxy/errors-custom/503.http rename to build/assets/etc/haproxy/errors-custom/503.http diff --git a/assets/etc/haproxy/errors-custom/504.http b/build/assets/etc/haproxy/errors-custom/504.http similarity index 100% rename from assets/etc/haproxy/errors-custom/504.http rename to build/assets/etc/haproxy/errors-custom/504.http diff --git a/docker-compose.yml b/deploy/docker/docker-compose.yml similarity index 88% rename from docker-compose.yml rename to deploy/docker/docker-compose.yml index 2af38f1..90b0a3e 100644 --- a/docker-compose.yml +++ b/deploy/docker/docker-compose.yml @@ -23,10 +23,15 @@ services: - "443:443/tcp" - "1936:1936/tcp" + networks: + - easyhaproxy + volumes: certs_letsencrypt: + external: true certs_haproxy: + external: true networks: easyhaproxy: - driver: bridge + external: true diff --git a/deploy/docker/install.sh b/deploy/docker/install.sh new file mode 100755 index 0000000..d5ab2ff --- /dev/null +++ b/deploy/docker/install.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +ASSETS_DIR="$(dirname "${BASH_SOURCE[0]}")"/../../build/assets/certs/haproxy + +docker network create easyhaproxy +docker volume create certs_letsencrypt +docker volume create certs_haproxy + +docker run -d --rm --name easyhaproxy_install -v certs_haproxy:/certs alpine tail -f /dev/null +docker cp $ASSETS_DIR/.place_holder_cert.pem easyhaproxy_install:/certs/.place_holder_cert.pem +docker stop easyhaproxy_install + +echo +echo +echo make sure to add to all of your containers: +echo +echo docker-compose +echo ============== +echo "networks:" +echo " default:" +echo " name: easyhaproxy" +echo " external: true" + +echo +echo +echo docker run +echo ============== +echo docker run ... --network easyhaproxy ... your_image:tag +echo \ No newline at end of file diff --git a/examples/kubernetes/easyhaproxy.yml b/deploy/kubernetes/easyhaproxy.yml similarity index 99% rename from examples/kubernetes/easyhaproxy.yml rename to deploy/kubernetes/easyhaproxy.yml index 1f54f2e..b4ee2ad 100644 --- a/examples/kubernetes/easyhaproxy.yml +++ b/deploy/kubernetes/easyhaproxy.yml @@ -4,7 +4,6 @@ kind: Namespace metadata: name: easyhaproxy - --- apiVersion: v1 kind: ServiceAccount @@ -86,7 +85,6 @@ subjects: name: easyhaproxy-ingress namespace: easyhaproxy - --- apiVersion: apps/v1 kind: DaemonSet @@ -135,4 +133,3 @@ spec: value: "true" - name: EASYHAPROXY_SSL_MODE value: loose -