From 020975158d47c38a27f98bc063f7fafd2f9daf00 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sun, 8 Oct 2023 16:44:05 +0200 Subject: [PATCH] feat(meta): Initial cookiecutter commit (#1) --- README.md | 121 ++++++++++++++++++++++- build-context/nginx/Dockerfile | 14 +++ build-context/nginx/docker-data/.gitkeep | 0 build-context/nginx/extras/.gitkeep | 0 build-context/ping/Dockerfile | 14 +++ build-context/ping/docker-data/.gitkeep | 0 build-context/ping/extras/.gitkeep | 0 common-settings.yml | 11 +++ docker-compose.override.yml | 19 ++++ docker-compose.yml | 72 ++++++++++++++ env/fqdn_context.env.example | 33 +++++++ 11 files changed, 283 insertions(+), 1 deletion(-) create mode 100644 build-context/nginx/Dockerfile create mode 100644 build-context/nginx/docker-data/.gitkeep create mode 100644 build-context/nginx/extras/.gitkeep create mode 100644 build-context/ping/Dockerfile create mode 100644 build-context/ping/docker-data/.gitkeep create mode 100644 build-context/ping/extras/.gitkeep create mode 100644 common-settings.yml create mode 100644 docker-compose.override.yml create mode 100644 docker-compose.yml create mode 100644 env/fqdn_context.env.example diff --git a/README.md b/README.md index f17ba80..9a862f6 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,121 @@ -# nginx +# FIXME +Search and replace all mentions of FIXME with sensible content in this file and in [docker-compose.yml](docker-compose.yml). + +# Nginx Docker Compose files + +Docker Compose files to spin up an instance of Nginx. + +# How to run + +Add a `COMPOSE_ENV` file and save its location as a shell variable along with the location where this repo lives, here for example `/opt/containers/nginx` plus all other variables. At [env/fqdn_context.env.example](env/fqdn_context.env.example) you'll find an example environment file. + +When everything's ready start Nginx with Docker Compose, otherwise head down to [Initial setup](#initial-setup) first. + +## Environment +``` +export COMPOSE_DIR='/opt/containers/nginx_' +export COMPOSE_CTX='ux_vilnius' +export COMPOSE_PROJECT='nginx-'"${COMPOSE_CTX}" +export COMPOSE_FILE="${COMPOSE_DIR}"'/docker-compose.yml' +export COMPOSE_OVERRIDE="${COMPOSE_DIR%/}"'/docker-compose.override.yml' +export COMPOSE_ENV= +``` + +## Context + +On your deployment machine create the necessary Docker context to connect to and control the Docker daemon on whatever target host you'll be using, for example: +``` +docker context create fully.qualified.domain.name --docker 'host=ssh://root@fully.qualified.domain.name' +``` + +## Build +FIXME We build the `nginx` image locally. Our adjustment to the official image is simply adding `/tmp/nginx` to it. See [build-context/nginx/Dockerfile](build-context/nginx/Dockerfile). We use `/tmp/nginx` to bind-mount a dedicated ZFS dataset for the application's `tmpdir` location. + +``` +docker compose --project-name "${COMPOSE_PROJECT}" --file "${COMPOSE_FILE}" --file "${COMPOSE_OVERRIDE}" --env-file "${COMPOSE_ENV}" --profile 'build-nginx' build +``` + +## Pull + +FIXME Rewrite either [Build](#build) or this paragraph for which images are built and which ones pulled, `--profile 'full'` may not make sense FIXME Pull images from Docker Hub verbatim. + +``` +docker compose --project-name "${COMPOSE_PROJECT}" --file "${COMPOSE_FILE}" --env-file "${COMPOSE_ENV}" --profile 'full' pull +``` + +## Copy to target + +Copy images to target Docker host, that is assuming you deploy to a machine that itself has no network route to reach Docker Hub. Copying in its simplest form involves a local `docker save` and a remote `docker load`. Consider the helper mini-project [quico.space/Quico/copy-docker](https://quico.space/Quico/copy-docker) where [copy-docker.sh](https://quico.space/Quico/copy-docker/src/branch/main/copy-docker.sh) allows the following workflow: + +``` +source "${COMPOSE_ENV}" +# FIXME Docker Hub image name with or without slash? FIXME +for image in 'nginx:'"${NGINX_VERSION}" 'ping:'"${PING_VERSION}"; do + copy-docker.sh "${image}" fully.qualified.domain.name +done +``` + +## Start + +``` +docker --context 'fully.qualified.domain.name' compose --project-name "${COMPOSE_PROJECT}" --file "${COMPOSE_FILE}" --env-file "${COMPOSE_ENV}" --profile 'full' up --detach +``` + +# Initial setup + +We're assuming you run Docker Compose workloads with ZFS-based bind mounts. ZFS management, creating a zpool and setting adequate properties for its datasets is out of scope of this document. + +## Datasets + +Create ZFS datasets and set permissions as needed. + +* Parent dateset + ``` + zfs create -o mountpoint=/opt/docker-data 'zpool/docker-data' + ``` + +* Container-specific datasets + ``` + zfs create -p 'zpool/docker-data/nginx-'"${COMPOSE_CTX}"'/nginx/data/db' + zfs create -p 'zpool/docker-data/nginx-'"${COMPOSE_CTX}"'/nginx/data/logs' + zfs create -p 'zpool/docker-data/nginx-'"${COMPOSE_CTX}"'/nginx/config' + zfs create -p 'zpool/docker-data/nginx-'"${COMPOSE_CTX}"'/ping/data/db' + zfs create -p 'zpool/docker-data/nginx-'"${COMPOSE_CTX}"'/ping/data/logs' + zfs create -p 'zpool/docker-data/nginx-'"${COMPOSE_CTX}"'/ping/config' + ``` + FIXME When changing bind mount locations to real ones remember to also update `volumes:` in [docker-compose.yml](docker-compose.yml) FIXME + +* Create subdirs + ``` + mkdir -p '/opt/docker-data/nginx-'"${COMPOSE_CTX}"'/nginx/'{'.ssh','config','data','projects'} + ``` + +* Change ownership + ``` + chown -R 1000:1000 '/opt/docker-data/nginx-${COMPOSE_CTX}/nginx/data/'{*,.*} + ``` + +## Additional files + +Place the following files on target server. Use the directory structure at [build-context](build-context) as a guide, specifically at `docker-data`. + +FIXME Add details about files that aren't self-explanatory FIXME + +``` +build-context/ +├── nginx +│ ├── docker-data +│ | └── config +│ │ └── nginx.cfg +│ ├── ... +│ └── ... +└── ping + ├── docker-data + | └── config + │ └── ping.cfg + ├── ... + └── ... +``` + +When done head back up to [How to run](#how-to-run). diff --git a/build-context/nginx/Dockerfile b/build-context/nginx/Dockerfile new file mode 100644 index 0000000..abf407f --- /dev/null +++ b/build-context/nginx/Dockerfile @@ -0,0 +1,14 @@ +# For the remainder of this Dockerfile EXAMPLE_ARG_FOR_DOCKERFILE will be +# available with a value of 'must_be_available_in_dockerfile', check out the env +# file at 'env/fully.qualified.domain.name.example' for reference. +# ARG EXAMPLE_ARG_FOR_DOCKERFILE + +# Another env var, this one's needed in the example build step below: +# ARG NGINX_VERSION + +# Example +# FROM "nginx:${NGINX_VERSION}" +# RUN apt-get update && \ +# apt-get -y install \ +# somepackage-6.q16-6-extra && \ +# rm -rf /var/lib/apt/lists/* diff --git a/build-context/nginx/docker-data/.gitkeep b/build-context/nginx/docker-data/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/build-context/nginx/extras/.gitkeep b/build-context/nginx/extras/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/build-context/ping/Dockerfile b/build-context/ping/Dockerfile new file mode 100644 index 0000000..df5be0a --- /dev/null +++ b/build-context/ping/Dockerfile @@ -0,0 +1,14 @@ +# For the remainder of this Dockerfile EXAMPLE_ARG_FOR_DOCKERFILE will be +# available with a value of 'must_be_available_in_dockerfile', check out the env +# file at 'env/fully.qualified.domain.name.example' for reference. +# ARG EXAMPLE_ARG_FOR_DOCKERFILE + +# Another env var, this one's needed in the example build step below: +# ARG PING_VERSION + +# Example +# FROM "ping:${PING_VERSION}" +# RUN apt-get update && \ +# apt-get -y install \ +# somepackage-6.q16-6-extra && \ +# rm -rf /var/lib/apt/lists/* diff --git a/build-context/ping/docker-data/.gitkeep b/build-context/ping/docker-data/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/build-context/ping/extras/.gitkeep b/build-context/ping/extras/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/common-settings.yml b/common-settings.yml new file mode 100644 index 0000000..9fd26d7 --- /dev/null +++ b/common-settings.yml @@ -0,0 +1,11 @@ +services: + common-settings: + environment: + TZ: "${TIMEZONE:-Etc/UTC}" + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "10" + compress: "true" + restart: "${RESTARTPOLICY:-unless-stopped}" diff --git a/docker-compose.override.yml b/docker-compose.override.yml new file mode 100644 index 0000000..75f744f --- /dev/null +++ b/docker-compose.override.yml @@ -0,0 +1,19 @@ +services: + nginx-build: + image: "nginx:${NGINX_VERSION}" + profiles: ["build", "build-nginx"] + build: + context: "build-context/nginx" + dockerfile: Dockerfile + args: + EXAMPLE_ARG_FOR_DOCKERFILE: "${EXAMPLE_ARG_FROM_ENV_FILE}" + NGINX_VERSION: "${NGINX_VERSION}" + ping-build: + image: "ping:${PING_VERSION}" + profiles: ["build", "build-ping"] + build: + context: "build-context/ping" + dockerfile: Dockerfile + args: + EXAMPLE_ARG_FOR_DOCKERFILE: "${EXAMPLE_ARG_FROM_ENV_FILE}" + PING_VERSION: "${PING_VERSION}" diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..5084241 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,72 @@ +services: + nginx: + # FIXME Docker Hub image name with or without slash? FIXME + image: "nginx:${NGINX_VERSION}" + container_name: "nginx-nginx-${CONTEXT}" + networks: + nginx-default: + profiles: ["full", "nginx"] + depends_on: + ping: + condition: service_healthy + ulimits: + nproc: ${ULIMIT_NPROC-65535} + nofile: + soft: ${ULIMIT_NPROC-65535} + hard: ${ULIMIT_NPROC-65535} + extends: + file: common-settings.yml + service: common-settings + ports: + # - "8080:80" + volumes: + # When changing bind mount locations to real ones remember to + # also update "Initial setup" section in README.md. + # - /opt/docker-data/nginx-${CONTEXT}/nginx/data/db:/usr/lib/nginx + # - /opt/docker-data/nginx-${CONTEXT}/nginx/data/logs:/var/log/nginx + # - /opt/docker-data/nginx-${CONTEXT}/nginx/config:/etc/nginx + environment: + # NGINX_USER: ${NGINX_USER} + # NGINX_PASSWORD: ${NGINX_PASSWORD} + ping: + # FIXME Docker Hub image name with or without slash? FIXME + image: "ping:${PING_VERSION}" + container_name: "nginx-ping-${CONTEXT}" + networks: + nginx-default: + profiles: ["full", "ping"] + healthcheck: + test: ["CMD", "fping", "--count=1", "${NGINX_VIP}", "--period=500", "--quiet"] + interval: 3s + timeout: 1s + retries: 60 + start_period: 2s + ulimits: + nproc: ${ULIMIT_NPROC-65535} + nofile: + soft: ${ULIMIT_NPROC-65535} + hard: ${ULIMIT_NPROC-65535} + extends: + file: common-settings.yml + service: common-settings + ports: + # - "8080:80" + volumes: + # When changing bind mount locations to real ones remember to + # also update "Initial setup" section in README.md. + # - /opt/docker-data/nginx-${CONTEXT}/ping/data/db:/usr/lib/ping + # - /opt/docker-data/nginx-${CONTEXT}/ping/data/logs:/var/log/ping + # - /opt/docker-data/nginx-${CONTEXT}/ping/config:/etc/ping + environment: + # PING_USER: ${PING_USER} + # PING_PASSWORD: ${PING_PASSWORD} +networks: + nginx-default: + name: nginx-${CONTEXT} + driver: bridge + driver_opts: + com.docker.network.enable_ipv6: "false" + ipam: + driver: default + config: + - subnet: ${SUBNET} diff --git a/env/fqdn_context.env.example b/env/fqdn_context.env.example new file mode 100644 index 0000000..b0fbdd9 --- /dev/null +++ b/env/fqdn_context.env.example @@ -0,0 +1,33 @@ +CONTEXT=ux_vilnius + + + +# Set something sensible here and uncomment +# --- +# NGINX_VERSION=x.y.z +# PING_VERSION=x.y.z +# NGINX_VIP=10.1.1.2 + + + +# Feel free to leave defaults. They apply while these vars are commented out +# --- +# RESTARTPOLICY=unless-stopped +# TIMEZONE=Etc/UTC + + + +# Subnet to use for this Docker Compose project. Docker defaults to +# container networks in prefix 172.16.0.0/12 which is 1 million addresses in +# the range from 172.16.0.0 to 172.31.255.255. Docker uses 172.17.0.0/16 for +# itself. Use any sensible prefix in 172.16.0.0/12 here except for Docker's +# own 172.17.0.0/16. +# --- +SUBNET=172.30.95.0/24 + + + +# See 'docker-compose.override.yml' for how to make a variable available in +# a Dockerfile +# --- +# EXAMPLE_ARG_FROM_ENV_FILE=must_be_available_in_dockerfile