Docker - sgml/signature GitHub Wiki

Localhost vs CI

CircleCI
(.circleci/config.yml)
GitLab CI
(.gitlab-ci.yml)
GitHub Actions
(.github/workflows/main.yml)
Docker Compose
(docker-compose.yml)
version: 2.1
jobs:
  build:
    docker:
      - image: cimg/python:3.10
    steps:
      - checkout
      - run:
          name: Diagnostics
          command: |
            echo "User: $(whoami)"
            echo "CPU: $(nproc)"
            echo "Memory:"
            free -h
            env | grep CIRCLE
      
stages:
  - build
build-job:
  image: python:3.10
  script:
    - echo "User: $(whoami)"
    - echo "CPU: $(nproc)"
    - echo "Memory:"
    - free -h
    - env | grep CI
      
name: CI Diagnostics
on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Diagnostics
        run: |
          echo "User: $(whoami)"
          echo "CPU: $(nproc)"
          echo "Memory:"
          free -h
          env | grep GITHUB
      
version: '3.8'
services:
  diagnostics:
    image: python:3.10
    entrypoint: /bin/bash
    command: >
      -c "echo 'User: $(whoami)' &&
          echo 'CPU: $(nproc)' &&
          echo 'Memory:' &&
          free -h &&
          env | grep DOCKER"
      

Docker Ontology

Docker Architecture

Image Layers

codex_title: Dual Python Layer Overlay for Reproducible Build/Runtime Separation

docker_keyword_glossary:
  FROM:
    description: Declares the base image for a build stage.
    compliance_affordance: Surfaces interpreter lineage and upstream provenance.

  WORKDIR:
    description: Sets the working directory for subsequent instructions.
    compliance_affordance: Prevents inherited state and enforces reproducible context.

  COPY:
    description: Transfers files from source to destination within the image.
    compliance_affordance: Ensures explicit file lineage and metadata traceability.

  RUN:
    description: Executes shell commands during image build.
    compliance_affordance: Enables reproducible transformations and audit-friendly scripting.

  ENTRYPOINT:
    description: Defines the default executable for the container.
    compliance_affordance: Locks execution path and prevents ambiguous runtime behavior.

  --from:
    description: References artifacts from a named build stage.
    compliance_affordance: Enables multi-stage builds and isolates dependency lineage.

infrastructure_codex:
  dockerfile_lineage:
    stages:
      - name: build
        base_image: python:3.10-slim
        purpose: compile artifacts and export dependency manifests
        interpreter:
          version: 3.10
          source: official Docker image
        working_directory: /app
        pyproject_path: /app/pyproject.toml
        commands:
          - WORKDIR /app
          - COPY pyproject.toml poetry.lock ./
          - RUN pip install poetry
          - RUN poetry export --without-hashes --with=dev --format=requirements.txt > /tmp/requirements.txt
        compliance_affordances:
          - reproducible dependency export
          - isolated build environment
          - audit-friendly manifest generation
          - surfaced project metadata lineage

      - name: runtime
        base_image: python:3.10-slim
        purpose: execute application with compiled Python 3.13
        interpreter:
          version: 3.13
          source: compiled from https://www.python.org/ftp/python/3.13.0/Python-3.13.0.tgz
          install_path: /opt/python3.13
        working_directory: /app
        pyproject_path: /app/pyproject.toml
        commands:
          - WORKDIR /app
          - COPY --from=build /tmp/requirements.txt /app/
          - COPY pyproject.toml poetry.lock ./
          - RUN /opt/python3.13/bin/python3.13 -m pip install -r requirements.txt
          - ENTRYPOINT ["/opt/python3.13/bin/python3.13", "main.py"]
        compliance_affordances:
          - explicit interpreter provenance
          - runtime isolation
          - reproducible execution path
          - mirrored project metadata for runtime introspection

  symbolic_hygiene:
    - codex title surfaced for lineage and traceability
    - pyproject.toml path surfaced in both layers for reproducibility
    - WORKDIR reset across stages to avoid inherited state
    - ENTRYPOINT explicitly defined to prevent ambiguous execution
    - interpreter lineage and project metadata surfaced for audit and drift detection

  reproducibility_guarantees:
    - dual-version compatibility
    - pinned Poetry version
    - checksum validation of exported requirements
    - mirrored project metadata across build/runtime boundaries

Lifecycle

-- Table: baz — Canonical State Enumeration
CREATE TABLE baz (
    state_code TEXT PRIMARY KEY,         -- e.g., 'created', 'running', 'exited'
    description TEXT NOT NULL,
    is_terminal BOOLEAN DEFAULT 0
);

-- Table: bar — State Transition Ledger (Epoch Timestamp as Primary Key)
CREATE TABLE bar (
    transition_time INTEGER PRIMARY KEY, -- Unix epoch timestamp (seconds or ms)
    container_id TEXT NOT NULL,          -- Foreign key to foo.container_id
    from_state TEXT,                     -- Nullable for initial state
    to_state TEXT NOT NULL,              -- Must exist in baz.state_code
    actor TEXT,                          -- Who/what initiated the transition
    FOREIGN KEY (to_state) REFERENCES baz(state_code)
);

-- Table: foo — Current Container State
CREATE TABLE foo (
    container_id TEXT PRIMARY KEY,
    current_state TEXT NOT NULL,
    last_updated INTEGER DEFAULT (strftime('%s','now')), -- Unix epoch
    FOREIGN KEY (current_state) REFERENCES baz(state_code)
);

Config

Dockerfile as the Model

# Dockerfile
ARG APP_PORT=3000
ENV APP_PORT=${APP_PORT}

Docker Compose as the View

# docker-compose.yml
services:
  web:
    build:
      context: .
      args:
        APP_PORT: ${APP_PORT}
    environment:
      - APP_PORT=${APP_PORT}
    env_file:
      - .env

CLI as the Controller

# Runtime
docker run --env APP_PORT=3000 myimage
docker inspect container_id | jq '.Config.Env'

Bad Defaults

  resource_limitations:
    cpu:
      description: "Containers share CPU with the host unless limited via --cpus or --cpu-shares"
      impact:
        - "High CPU usage by containers can starve host processes"
        - "Performance degradation under load without limits"
    ram:
      description: "Containers use host memory unless constrained via --memory"
      impact:
        - "Memory overcommitment can lead to OOM kills"
        - "No swap usage unless explicitly configured"
    disk_space:
      description: "Images, containers, volumes, and logs consume disk space"
      impact:
        - "Docker can fill up /var/lib/docker rapidly"
        - "No automatic cleanup unless using pruning or log rotation"
      mitigation:
        - "Use 'docker system prune' regularly"
        - "Configure log driver with size limits"
        - "Monitor disk usage with 'docker system df'"

  security_tips:
    - "Restrict SSH access to trusted IPs via firewall"
    - "Use SSH keys, not passwords"
    - "Ensure 'foo' has limited sudo access if needed"

Risks and Mitigations

  unsafe_defaults_and_limitations:
    username/password:
      description: It's root/root
      issue: Say no more
      mitigation: rootless
      cannot be disabled: false

    docker_socket:
      description: "/var/run/docker.sock grants root-level access to the host"
      issue: "Mounting this socket into containers allows full control of Docker daemon"
      mitigation: "Avoid mounting the socket; use SSH-based access or rootless Docker"
      cannot_be_disabled: true

    default_networking:
      description: "Containers are attached to the default 'bridge' network (docker0)"
      issue: "All containers can communicate freely unless isolated"
      mitigation: "Use custom user-defined bridge networks with subnet and firewall rules"
      cannot_be disabled: true

    privileged_mode:
      description: "--privileged flag disables most container isolation"
      issue: "Grants access to host devices and kernel capabilities"
      mitigation: "Avoid using privileged containers unless absolutely necessary"
      cannot_be_disabled: true

    default_user:
      description: "Containers run as root by default"
      issue: "Increases risk of privilege escalation and host compromise"
      mitigation: "Set USER in Dockerfile or use -u flag during runtime"
      cannot_be_disabled: true

    insecure_registry:
      description: "Docker allows pushing/pulling from insecure registries if configured"
      issue: "Unencrypted traffic and potential MITM attacks"
      mitigation: "Use TLS-secured registries; avoid 'insecure-registries' unless isolated"
      cannot_be_disabled: false

    image trust:
      description: "Docker does not verify image signatures by default"
      issue: "Images may be tampered with or come from untrusted sources"
      mitigation: "Use Docker Content Trust (DCT) and signed images"
      cannot_be_disabled: false

    resource overcommit:
      description: "Containers can consume unlimited CPU/RAM unless constrained"
      issue: "Can starve host or other containers"
      mitigation: "Use --memory, --cpus, and cgroups"
      cannot_be_disabled: true

    logging:
      description: "Default logging driver ('json-file') can grow unbounded"
      issue: "Can fill disk space rapidly"
      mitigation: "Configure log rotation or use alternative drivers like 'syslog'"
      cannot_be_disabled: false

    kernel sharing:
      description: "Containers share the host kernel"
      issue: "Kernel vulnerabilities affect all containers"
      mitigation: "Keep host OS and kernel patched; consider rootless mode"
      cannot_be_disabled: true

SSH

docker_ssh_only_setup:
  prerequisites:
    - "Docker installed on remote host"
    - "SSH access with user 'foo' in the 'docker' group"
    - "SSH key-based authentication configured"
    - "No TLS, TCP, or UNIX socket exposure"

  dockerd_configuration:
    method: "Default dockerd setup (no special flags needed)"
    notes:
      - "Do not expose TCP via --host=tcp://..."
      - "Do not modify daemon.json for TLS or socket changes"
      - "Ensure dockerd is running and accessible to 'foo' via SSH"
    confirm_running_over_ssh:
      command: "ssh [email protected] 'pgrep dockerd && echo dockerd is running'"
      expected_output: "PID of dockerd process and confirmation message"

  docker_cli_context:
    create_context:
      command: >
        docker context create \
          --docker "host=ssh://[email protected]" \
          local-ssh
    use_context:
      command: "docker context use local-ssh"
    verify_connection:
      command: "docker info"
    confirm_tls_disabled:
      command: "echo $DOCKER_TLS_VERIFY"
      expected_output: "Empty string (TLS is disabled)"
    notes:
      - "This sets up Docker CLI to communicate over SSH"
      - "No need to expose or bind to /var/run/docker.sock"

  ssh_config:
    path: "~/.ssh/config"
    entry:
      Host 127.0.0.1
      User foo
      IdentityFile ~/.ssh/id_rsa
      ControlMaster auto
      ControlPath ~/.ssh/control-%C
      ControlPersist yes

HTTP Only

Server Port

Set the port to 2375 explicitly:

dockerd -H unix:///var/run/docker.sock -H tcp://127.0.0.1:2375

OR Link-Local: 99 dockerd -H tcp://169.254.1.1:2375

Client Port

Set the environment variable:

export DOCKER_HOST=tcp://127.0.0.1:2375

OR Link-local:

export DOCKER_HOST=tcp://169.254.1.1:2375

then run:

docker

TLS

Set TLS but skip verification:

DOCKER_TLS_VERIFY=0

OR:

docker --tlsverify=false -H tcp://127.0.0.1:2376 info

Unset TLS in a RDBMS

Database How to Unset TLS
PostgreSQL Set ssl = off in postgresql.conf and use host (not hostssl) in pg_hba.conf
MariaDB Remove or comment out ssl_cert, ssl_key, and ssl_ca in my.cnf
Oracle Remove TCPS entries from sqlnet.ora and listener.ora; set SSL_CLIENT_AUTHENTICATION = FALSE
MySQL Remove ssl-ca, ssl-cert, and ssl-key from my.cnf; set tls-version=''

Unset HTTPS

error during connect: Get "https://127.0.0.1:2375/v1.51/info": http: server gave HTTP response to HTTPS client

Unset the following:

unset DOCKER_TLS_VERIFY
unset DOCKER_CERT_PATH

SSH

Use SSH instead of TCP

export DOCKER_HOST="ssh://[email protected]"

OR setup an alias:

alias docker='ssh [email protected] sudo docker'

Startup

Redirect stdout and stderr to dockerd.log and start as a background process:

dockerd &> ~/dockerd.log &

Verify:

docker info

Link-Local Limitations

Interactive Build

Run the build:

docker run

Each of the lines that says ---> 0123456789ab with a hex ID has a valid image ID. So from here you can

docker run --rm -it 12ebbdc1e72d sh

which will give you an interactive shell on the partial image resulting from the first RUN command.

Runtime IP Verification

Network Congestion

Golang Docker API

docker_golang_api_advantages:
  - programmatic_control:
      description: >
        The Go API allows developers to programmatically interact with Docker, enabling
        seamless automation and integration into applications. This provides more flexibility
        than manually executing Docker CLI commands.
      url: https://pkg.go.dev/github.com/docker/docker/client
  - fine_grained_control:
      description: >
        The Go API provides low-level control over Docker objects (e.g., containers, images,
        networks, volumes), allowing detailed customization of workflows.
      url: https://docs.docker.com/engine/api/
  - error_handling:
      description: >
        With the Go API, developers can implement robust and precise error handling directly in
        their applications, unlike parsing CLI error messages.
      url: https://pkg.go.dev/github.com/docker/docker/client#Client
  - integration_with_go_apps:
      description: >
        The Go API seamlessly integrates with Go applications, eliminating the need to
        invoke external processes or parse CLI output.
      url: https://pkg.go.dev/github.com/docker/docker/client
  - asynchronous_operations:
      description: >
        The Go API supports non-blocking, asynchronous operations for tasks such as
        container creation, which can improve efficiency in complex workflows.
      url: https://docs.docker.com/engine/api/v1.41/
  - custom_tooling:
      description: >
        Developers can create custom tools tailored to specific use cases using the API,
        such as deployment pipelines, monitoring tools, and container orchestration systems.
      url: https://pkg.go.dev/github.com/docker/docker
  - access_to_events:
      description: >
        The Go API enables subscribing to Docker events, such as container start/stop or
        image pull completion, which allows for real-time event-driven workflows.
      url: https://docs.docker.com/engine/api/v1.41/#tag/System/operation/SystemEvents
  - cross_platform_compatibility:
      description: >
        Applications built with the Go API can interact with Docker on any platform
        (Linux, macOS, Windows), ensuring consistent behavior across environments.
      url: https://pkg.go.dev/github.com/docker/docker
  - reduced_overhead:
      description: >
        By using the Go API, developers avoid spawning new processes to execute CLI commands,
        reducing latency and improving performance.
      url: https://pkg.go.dev/github.com/docker/docker
  - version_compatibility:
      description: >
        The Go API allows specifying the Docker API version to ensure compatibility
        with specific Docker Engine versions, providing greater control over behavior.
      url: https://docs.docker.com/engine/api/version-history/

Cookbook

# Status
systemctl status docker.service

# Stop
ps axf | grep docker | grep -v grep | awk '{print "kill -9 " $1}' | sudo sh
systemctl stop docker

# Start
systemctl start docker

# The Bad Parts
* https://dagster.io/blog/fast-deploys-with-pex-and-docker

# Verify Certificate Chain
openssl verify -CAfile RootCert.pem -untrusted Intermediate.pem UserCert.pem

# Verify Self-Signed Certificate
openssl verify -CAfile test.crt test.crt

QA

Error guessing is a testing technique that leverages the tester’s experience, intuition, and knowledge of the system to predict where defects might occur. Here's a general methodology:

  • Leverage Experience: Testers use their past experience with similar applications or common error patterns to guess where errors might occur in the current application.

  • Understand the System: Testers need a good understanding of the system, its context, and its users. This knowledge can help them predict what might go wrong.

  • Identify Risky Areas: Certain parts of an application might be more prone to errors. These could be complex features, areas where new changes have been made, or parts of the application that have had issues in the past.

  • Design Test Cases: Based on their guesses, testers design and execute test cases specifically to expose potential errors.

  • Learn and Adapt: As testers find defects, they learn more about the system’s behavior and can refine their error guessing strategy.

Daemon

https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html

Engine

Mutual TLS

Client

Troubleshooting

Five W's

Internals

Optimized Images

Commands

Exec

docker exec -it postgres-localhost bash
psql -U postgres
CREATE DATABASE mytestdb;

Volume Mappings

docker volume create --name my_dag_log_volume --opt type=none --opt device=$PWD/airflow/logs --opt o=bind
    volumes:
      - my_dag_log_volume:/usr/local/airflow/logs
volumes:
  my_dag_log_volume:

State

Stateless Components of Docker

Component Description MVC Stack Example
Docker CLI (docker) Stateless command-line interface; does not store persistent data Developer uses CLI to launch containers for MVC stack
Container runtime Containers are ephemeral unless volumes are used Stateless frontend container (e.g., React + Nginx) serving static assets
Docker images Immutable and read-only; do not change once built Prebuilt image of MVC frontend or API layer
Docker networks (default) Stateless unless custom rules or persistent IPs are configured Default bridge network connecting MVC containers temporarily
Logs (json-file driver) Ephemeral unless rotated or exported Frontend container logs discarded after restart
Docker context (SSH) Stateless transport layer; no persistent connection state SSH context used to deploy MVC stack remotely

Stateful Components of Docker

Component Description MVC Stack Example
Volumes Persist data across container restarts; used for databases, uploads, etc. PostgreSQL volume storing user accounts and session data
Bind mounts Link container paths to host filesystem; state depends on host files Mounting config files or uploaded media for MVC backend
Docker daemon (dockerd) Maintains metadata about containers, images, volumes, and networks Tracks running MVC containers and their volumes
Container state Includes running/stopped status, resource usage, and logs MVC backend container with persistent state and logs
Docker Compose files Define multi-container stateful applications with persistent volumes Compose file defining frontend, backend, and database services
Docker registry Stores and serves images; stateful by nature Private registry hosting custom MVC stack images
Overlay networks Maintain state across nodes for service discovery and routing Swarm overlay network for distributed MVC stack deployment
Docker Desktop Includes persistent VM and configuration state Local development of full MVC stack using Docker Desktop

Semi-Stateful Components of Docker

Component Description MVC Stack Example
Build cache Stores intermediate layers to speed up rebuilds Cached layers from building MVC backend with Node.js
Image layers Reused across containers; not persistent per container but shared globally Shared base image for frontend and backend (e.g., Node or Python base)
Docker context metadata Stores context definitions locally but not on the remote host Local context for deploying MVC stack to staging or production
Container logs (rotated) Persist temporarily depending on log driver and rotation settings Rotated logs from MVC backend container
Network aliases Persist only while containers are running Temporary alias for frontend to reach backend via service name
BuildKit session Retains temporary state during multi-stage builds Multi-stage Dockerfile for building and packaging MVC frontend assets

Concepts

https://docs.docker.com/glossary/

https://dockerbook.com/TheDockerBook_sample.pdf

https://docs.docker.com/compose/release-notes/

https://docs.docker.com/compose/gettingstarted/

https://vsupalov.com/docker-arg-env-variable-guide/

https://www.techrepublic.com/article/what-is-the-difference-between-dockerfile-and-docker-compose-yml-files/

YAML

https://github.com/compose-spec/compose-spec/blob/main/spec.md

https://docs.docker.com/config/containers/live-restore/

https://docs.docker.com/compose/compose-file/

https://github.com/docker-library/postgres/issues/581

Debugging

https://www.joyfulbikeshedding.com/blog/2019-08-27-debugging-docker-builds.html

https://medium.com/@betz.mark/ten-tips-for-debugging-docker-containers-cde4da841a1d

https://rasa.com/docs/rasa-x/installation-and-setup/docker-compose-manual/

Directives

https://design.jboss.org/redhatdeveloper/marketing/docker_cheatsheet/cheatsheet/images/docker_cheatsheet_r3v2.pdf

https://duo.com/decipher/docker-bug-allows-root-access-to-host-file-system

Environment Variables

https://docs.docker.com/compose/environment-variables/

https://www.quora.com/Is-there-a-way-to-change-environment-variables-from-outside-a-Docker-container-If-we-have-a-server-already-running-is-there-a-clever-technique-we-can-use-to-change-the-environment-variables-without-rebuilding-the

https://code.visualstudio.com/docs/remote/containers-advanced

https://docs.docker.com/compose/reference/envvars/

User/Group Permissions

https://docs.docker.com/engine/install/linux-postinstall/

https://dev.to/acro5piano/specifying-user-and-group-in-docker-i2e

https://stackoverflow.com/questions/40462189/docker-compose-set-user-and-group-on-mounted-volume

https://code.visualstudio.com/docs/containers/python-user-rights

https://medium.com/@nielssj/docker-volumes-and-file-system-permissions-772c1aee23ca

https://stackoverflow.com/questions/52754149/operation-of-the-mkdir-command-with-dockerfile/52754409

https://github.com/moby/moby/issues/20920

https://stackoverflow.com/questions/52737690/how-to-copy-a-directory-over-the-docker-cp

Race Conditions

https://labouardy.com/preventing-race-conditions-in-docker/

https://github.com/moby/moby/issues/26768

https://github.com/moby/moby/issues/38064

https://www.digitalocean.com/community/tutorials/how-to-debug-and-fix-common-docker-issues

https://www.digitalocean.com/community/questions/how-to-fix-docker-got-permission-denied-while-trying-to-connect-to-the-docker-daemon-socket

Wordpress

https://devtidbits.com/2019/11/02/customise-wordpress-on-docker/

Postgres

https://github.com/Radu-Raicea/Dockerized-Flask/wiki/[Docker]-Access-the-PostgreSQL-command-line-terminal-through-Docker

https://stackoverflow.com/questions/26598738/how-to-create-user-database-in-script-for-docker-postgres

https://davejansen.com/how-to-set-up-and-use-postgres-using-docker/

https://markheath.net/post/exploring-postgresql-with-docker

https://medium.com/better-programming/connect-from-local-machine-to-postgresql-docker-container-f785f00461a7

https://medium.com/coderbunker/rapid-api-development-tutorial-with-docker-postgresql-postgraphile-e387c1c73dd8

https://hackernoon.com/dont-install-postgres-docker-pull-postgres-bee20e200198

https://medium.com/@mikaelino/querying-a-database-with-graphql-and-dataloader-an-introduction-in-go-d8d2609bc635

https://medium.com/@harshityadav95/postgresql-in-windows-subsystem-for-linux-wsl-6dc751ac1ff3

https://medium.com/@stephanedmonson/solution-for-connecting-postgresql-via-wsl-windows-subsystem-for-linux-ubuntu18-c79940fa5742

Docker Engine API

https://docs-stage.docker.com/engine/api/v1.24/

https://docs.microsoft.com/en-us/virtualization/windowscontainers/manage-docker/configure-docker-daemon

https://jackiechen.org/2015/04/20/understanding-docker-directory-structure/

Compose

https://docs.docker.com/compose/compose-file/compose-file-v2/

https://gist.github.com/eliashussary/379e44a99e2389bd6a8ea6a23c2d5af8

https://bobcares.com/blog/docker-change-container-configuration/

https://linuxhint.com/run_postgresql_docker_compose/

https://stackoverflow.com/questions/44198512/howto-pass-postgres-user-env-variable-when-using-docker-compose-yml-for-docker

Inspect

https://www.mankier.com/1/docker-inspect

Debian

https://wiki.debian.org/nftables

https://lwn.net/Articles/676831/

Network

https://docs.docker.com/network/

https://stackoverflow.com/questions/36454955/docker-and-netstat-netstat-is-not-showing-ports-exposed-by-docker-containers

https://docs.docker.com/v17.09/engine/userguide/networking/configure-dns/

https://forums.docker.com/t/docker-pull-not-using-correct-dns-server-when-private-registry-on-vpn/11117

Clustering

https://www.godaddy.com/engineering/2018/05/02/kubernetes-introduction-for-developers/

https://azure.microsoft.com/en-us/resources/cloud-computing-dictionary/what-is-kubernetes/#beyond-kubernetes

File/Directory/Volume Bind Mounts

X11

Containers

https://docs.docker.com/config/containers/live-restore/

Startup/Shutdown

https://docs.docker.com/config/daemon/systemd/

https://coreos.com/os/docs/latest/customizing-docker.html

http://www.softpanorama.org/Commercial_linuxes/Startup_and_shutdown/systemd.shtml

http://www.softpanorama.org/Commercial_linuxes/RHEL/index.shtml

https://www.slideshare.net/SreenivasMakam/docker-networking-common-issues-and-troubleshooting-techniques

https://docker-py.readthedocs.io/en/stable/volumes.html

https://docs.docker.com/storage/volumes/

Daemon

https://docs.docker.com/config/daemon/

https://docs.docker.com/engine/security/https/

https://www.bennadel.com/blog/3419-from-noob-to-docker-on-digitalocean-with-nginx-node-js-datadog-logs-dogstatsd-and-letsencrypt-ssl-certificates.htm

https://www.linkedin.com/pulse/use-apache-ssllets-encrypt-docker-leon-sczepansky/

https://docs.docker.com/engine/reference/commandline/dockerd/

http://dockerlabs.collabnix.com/beginners/components/daemon/

https://support.coreos.com/hc/en-us/articles/115002311127-Debugging-docker-daemon-Issues

https://github.com/docker/cli/issues/2104

https://serverfault.com/questions/681571/docker-exposed-ports-accessible-from-outside-iptables-rules-ignored

Compile from Source(s)

Gotchas

One issue that occurs semi-regularly for LtU is that bot attacks - often just from overly aggressive crawlers - can cause the database container to run out of resources and crash. In that case, Kubernetes usually restarts the container and everything recovers automatically within a few minutes.

This process worked well for a few years, but at some point, it stopped working seamlessly. Even after manual attempts to recover, there would still be an intermittent but frequent symptom where it seemed like the app was still trying to reach the old crashed container, or something like that. I spent a bit of time looking at it, but soon decided it would be easier to switch to a new cluster than debug that years-old setup.

Git Commit in a Docker Container

# Once you're in the container, you can install git.
apt-get update
apt-get install -y git

# Configure your Git user (replace with your own name and email).
git config --global user.name "Your Name"
git config --global user.email "[email protected]"

# Clone your repository (replace with your repository's URL).
git clone https://github.com/username/repository.git

# Navigate into your repository.
cd repository

# Make changes to your files here.

# Stage and commit your changes.
git add .
git commit -m "Your commit message"

# Push your changes (replace 'main' with your branch name if different).
git push origin main

Environment Variables

{
  "DOCKER_CERT_PATH": "Path to the directory containing Docker TLS certificates (e.g., ca.pem, cert.pem, key.pem). Used for secure communication with the Docker daemon.",
  "DOCKER_HOST": "Specifies the address of the Docker daemon (e.g., tcp://localhost:2376). Determines where Docker CLI communicates with the Docker engine.",
  "DOCKER_TLS_VERIFY": "Set to '1' to enable TLS verification for secure communication with the Docker daemon. If unset or set to '0', TLS verification is disabled.",
  "DOCKER_API_VERSION": "Specifies the version of the Docker API to use. For compatibility, it's recommended to set this explicitly.",
  "DOCKER_BUILDKIT": "Enables BuildKit, an advanced build subsystem for Docker. Set to '1' to enable BuildKit features during image builds.",
  "DOCKER_REGISTRY": "Specifies the default registry to use for pulling images. Useful when working with private registries.",
  "DOCKER_USERNAME": "Username for authentication when pushing or pulling images from a registry.",
  "DOCKER_PASSWORD": "Password for authentication when pushing or pulling images from a registry.",
  "DOCKER_IMAGE_TAG": "Default tag to use when pulling or pushing images. If not specified, 'latest' is assumed.",
  "DOCKER_NETWORK": "Specifies the default network mode for containers (e.g., 'bridge', 'host', 'none').",
  "DOCKER_LOG_DRIVER": "Sets the default logging driver for containers (e.g., 'json-file', 'syslog', 'journald').",
  "DOCKER_STORAGE_DRIVER": "Specifies the storage driver for managing container filesystems (e.g., 'overlay2', 'aufs', 'zfs')."
}
{
  "options": {
    "-inform": "DER|PEM|NET",
    "-outform": "DER|PEM|NET",
    "-in": "filename",
    "-out": "filename",
    "-md2|-md5|-sha1|-mdc2": "digest to use",
    "-engine": "id",
    "-text": "prints out the certificate in text form",
    "-certopt": "customizes the output format used with -text"
  },
  "descriptions": {
    "-inform": "Specifies the input format (DER, PEM, or NET)",
    "-outform": "Specifies the output format (DER, PEM, or NET)",
    "-in": "Input filename to read a certificate from",
    "-out": "Output filename to write to",
    "-md2|-md5|-sha1|-mdc2": "Digest options for signing or display",
    "-engine": "Specifies an engine by its unique id",
    "-text": "Displays full certificate details",
    "-certopt": "Customizes the output format used with -text"
  }
}
+---------------------+
|                     |
|   Kubernetes API    |
|                     |
+---------------------+
          |
          v
+---------------------+
|                     |
|   Kubelet (Windows) |
|                     |
+---------------------+
          |
          v
+---------------------+
|                     |
|   Containerd        |
|                     |
+---------------------+
          |
          v
+---------------------+
|                     |
|   Windows Host OS   |
|                     |
+---------------------+
          |
          v
+---------------------+
|                     |
|   Windows Containers|
|                     |
+---------------------+

MTLS

package main

import (
    "crypto/rand"
    "crypto/rsa"
    "crypto/x509"
    "crypto/x509/pkix"
    "encoding/pem"
    "math/big"
    "os"
    "time"
)

func generateCert() {
    // Generate a private key
    priv, _ := rsa.GenerateKey(rand.Reader, 2048)

    // Create a certificate template
    template := x509.Certificate{
        SerialNumber: big.NewInt(1),
        Subject: pkix.Name{
            Organization: []string{"My Organization"},
        },
        NotBefore: time.Now(),
        NotAfter:  time.Now().Add(365 * 24 * time.Hour),
        KeyUsage:  x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
        ExtKeyUsage: []x509.ExtKeyUsage{
            x509.ExtKeyUsageServerAuth,
            x509.ExtKeyUsageClientAuth,
        },
        BasicConstraintsValid: true,
    }

    // Create a self-signed certificate
    certDER, _ := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)

    // Save the certificate and key to files
    certOut, _ := os.Create("cert.pem")
    pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: certDER})
    certOut.Close()

    keyOut, _ := os.Create("key.pem")
    pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
    keyOut.Close()
}

func main() {
    generateCert()
}

Postgresql.conf

ssl = on
ssl_cert_file = 'cert.pem'
ssl_key_file = 'key.pem'

Docker SDKs by Language (One per Language)

Go

Python

PHP

.NET

Java

JavaScript / Node.js

Ruby

Lifecycle

Client

CREATED
  ├── docker start
  │     └── RUNNING
  │           ├── docker pause
  │           │     └── PAUSED
  │           │           └── docker unpause
  │           │                 └── RUNNING
  │           └── docker stop
  │                 └── STOPPED
  │                       └── docker rm
  │                             └── REMOVED
  └── docker rm
        └── REMOVED

Server

CREATED
  ├── POST /containers/start
  │     └── RUNNING
  │           ├── POST /containers/pause
  │           │     └── PAUSED
  │           │           └── POST /containers/unpause
  │           │                 └── RUNNING
  │           └── POST /containers/stop
  │                 └── STOPPED
  │                       └── DELETE /containers/{id}
  │                             └── REMOVED
  └── DELETE /containers/{id}
        └── REMOVED

Windows, MacoOS, Linux Specific Differences

dockerd_platform_differences:
  Linux:
    virtualization: "None (runs natively)"
    socket_path: "/var/run/docker.sock"
    cgroups: "Fully supported"
    namespaces: "Fully supported"
    storage_path: "/var/lib/docker"
    root_modes:
      rootful:
        description: "Daemon runs as root with full system access"
        pros: ["High performance", "Unrestricted port binding", "Full feature support"]
        cons: ["Higher security risk if daemon is compromised"]
      rootless:
        description: "Daemon and containers run in user space without root privileges"
        pros: ["Improved security", "No root access required"]
        cons: ["Cannot bind to ports <1024", "Slight performance overhead"]
        components: ["slirp4netns", "fuse-overlayfs", "newuidmap/newgidmap"]
    notes:
      - "No Docker Desktop required"
      - "Best platform for rootless mode"

  macOS:
    virtualization: "Docker Desktop VM (HyperKit or Apple Virtualization)"
    socket_path: "Emulated inside VM"
    cgroups: "Not exposed to host"
    namespaces: "Limited via VM"
    storage_path: "Inside VM (not host-accessible)"
    root_modes:
      rootful:
        description: "Daemon runs as root inside VM"
        notes: ["No native rootless mode on host", "Security depends on VM isolation"]
    special_terms:
      - "moby: internal Linux VM"
      - "vpnkit: legacy networking layer"
      - "DOCKER_DEFAULT_PLATFORM: env var to force architecture"
    notes:
      - "Requires Docker Desktop"
      - "Rootless mode not supported natively"

  Windows:
    virtualization: "Docker Desktop VM (WSL2 or Hyper-V)"
    socket_path: "Emulated inside WSL2 VM"
    cgroups: "Not exposed to host"
    namespaces: "Limited via WSL2"
    storage_path: "Inside WSL2 VM"
    root_modes:
      rootful:
        description: "Daemon runs as root inside WSL2 VM"
        notes: ["No native rootless mode on host", "Security depends on WSL2 isolation"]
    special_terms:
      - "docker-desktop: WSL2 distro"
      - "docker-desktop-data: WSL2 volume"
      - "com.docker.service: privileged helper"
    notes:
      - "Requires Docker Desktop"
      - "Rootless mode not supported natively"

Monitoring

monitoring_pipeline:
  platform: "Amazon EC2 (Linux)"
  container_runtime: "Docker"
  alert_channels:
    - "Amazon SES (Simple Email Service)"
  schedule: "cron or systemd timer"

disk_monitoring:
  method: "Shell script using docker CLI"
  metrics:
    - "docker system df"
    - "docker volume ls --filter dangling=true"
    - "docker info | grep 'Space Available'"
  thresholds:
    data_space: "e.g., < 1GB"
    metadata_space: "e.g., < 500MB"
  actions:
    - "Log warning"
    - "Send alert via SES"
  script:
    path: "/opt/docker-monitor/disk_check.sh"
    log: "/var/log/docker-monitor/disk_check.log"

network_monitoring:
  method: "netstat or ss + docker inspect"
  checks:
    - "Detect exposed ports using docker inspect"
    - "Check if ports are reachable externally"
    - "Validate EC2 security group rules"
  thresholds:
    unexpected_ports: "e.g., ports not in allowlist"
    unreachable_ports: "e.g., mapped but not responding"
  actions:
    - "Log warning"
    - "Send alert via SES"
  script:
    path: "/opt/docker-monitor/port_check.sh"
    log: "/var/log/docker-monitor/port_check.log"

email_alerts:
  service: "Amazon SES"
  setup:
    - "Verify sender email/domain"
    - "Configure IAM role with SES send permissions"
  method: "Send email via AWS CLI or boto3"
  content:
    subject: "Docker Alert: Volume or Port Issue on EC2"
    body: "Include timestamp, instance ID, and warning details"
  script:
    path: "/opt/docker-monitor/send_alert.py"
    log: "/var/log/docker-monitor/email_alert.log"

scheduling:
  method: "cron or systemd timer"
  frequency: "e.g., every 15 minutes"
  config:
    cron_file: "/etc/cron.d/docker-monitor"
    systemd_timer: "/etc/systemd/system/docker-monitor.timer"
    systemd_service: "/etc/systemd/system/docker-monitor.service"

Wordpress Dockerization

Downgrade from ELB

wordpress_plugin_overlays:
  autoscaling:
    setup: external
    cost: AWS EC2 ASG (variable, ~$0.025/hr per instance + CloudWatch)
    instructions: |
      Use EC2 Auto Scaling Groups or Kubernetes HPA.
      - Define MinSize and MaxSize
      - Attach CloudWatch alarms for CPUUtilization
      - Ensure WordPress is stateless or uses shared storage
    replaces:
      aws:autoscaling:asg:
        MinSize: '.minSize'
        MaxSize: '4'
      aws:autoscaling:trigger:
        MeasureName: 'CPUUtilization'
        UpperThreshold: '60'
        LowerThreshold: '20'

  deployment:
    setup: manual
    cost: Free (using Git + WP-CLI + CI/CD)
    instructions: |
      Use Git hooks or CI/CD pipelines to deploy themes/plugins.
      - Clone repo into wp-content
      - Use `wp plugin activate` or `wp theme activate`
      - Script health checks and batch logic externally
    replaces:
      aws:elasticbeanstalk:command:
        DeploymentPolicy: 'Rolling'
        BatchSizeType: 'Fixed'
        BatchSize: '1'
        IgnoreHealthCheck: 'true'
      aws:autoscaling:updatepolicy:rollingupdate:
        RollingUpdateEnabled: true

  ssh_restriction:
    setup: EC2-level
    cost: Free (included in EC2/VPC provisioning)
    instructions: |
      Configure Security Groups:
      - Allow TCP port 22 only from trusted IPs
      - Use AWS Console or Terraform
    replaces:
      aws:autoscaling:launchconfiguration:
        SSHSourceRestriction: tcp, 22, 22, 0.0.0.0/0

  environment_variables:
    plugin: WP Config File Editor
    cost: Free
    notes: |
      Injects env vars via wp-config.php; manual or scripted.
    replaces:
      aws:elasticbeanstalk:application:environment:
        CIRCLE_BRANCH: '.circleBranch'

  php_configuration:
    plugin: WP Performance Score Booster
    cost: Free
    notes: |
      Adjusts PHP settings via .htaccess or ini overrides.
    replaces:
      aws:elasticbeanstalk:container:php:phpini:
        display_errors: 'Off'
      files:
        "/etc/php.d/04uploadsize.ini":
          content: upload_max_filesize=1000M
      container_commands:
        00change_php_post_max_size:
          command: sed -i '/post_max_size = /c\post_max_size = 1000M' /etc/php.d/aws.ini

  proxy_server:
    plugin: Nginx Helper
    cost: Free
    notes: |
      Manages cache purging and rewrite rules; requires Nginx backend.
    replaces:
      aws:elasticbeanstalk:environment:proxy:
        ProxyServer: 'nginx'

  monitoring:
    plugin: Query Monitor
    cost: Free
    notes: |
      Tracks performance, queries, hooks; no CloudWatch integration.
    replaces:
      aws:elasticbeanstalk:monitoring:
        Automatically Terminate Unhealthy Instances: 'false'
      aws:elasticbeanstalk:healthreporting:system:
        SystemType: 'enhanced'

  ssl_listener:
    setup: manual
    cost: Free (via Let's Encrypt); AWS ACM ~$0 (included with ELB)
    instructions: |
      Use Let's Encrypt or AWS ACM:
      - Provision SSL certs
      - Configure HTTPS in Nginx/Apache
      - Redirect HTTP to HTTPS
    replaces:
      aws:elb:listener:443:
        ListenerProtocol: 'HTTPS'
        SSLCertificateId: '.certificateArn'

  shared_storage:
    setup: manual
    cost: S3 storage (~$0.023/GB/month) + AWS bandwidth
    instructions: |
      Replace EFS with S3:
      - Use WP Offload Media (manual install)
      - Configure AWS credentials and bucket
      - Set upload path in wp-config.php
    replaces:
      Resources:
        FileSystem:
          Type: AWS::EFS::FileSystem
        MountTargetA:
          Type: AWS::EFS::MountTarget
        MountTargetB:
          Type: AWS::EFS::MountTarget

  datadog_php_fpm:
    setup: server-level
    cost: Datadog Agent (~$15–$23/month per host)
    instructions: |
      Install Datadog Agent:
      - Configure PHP-FPM with env vars
      - Restart php-fpm
      - Validate metrics in Datadog dashboard
    replaces:
      container_commands:
        04add_datadog_service_name:
          command: echo "env[DD_SERVICE] = community-site" >> /etc/php-fpm.d/www.conf
        05add_datadog_env:
          command: echo "env[DD_ENV] = $CIRCLE_BRANCH" >> /etc/php-fpm.d/www.conf

  upload_limits:
    plugin: Increase Maximum Upload File Size
    cost: Free
    notes: |
      Adjusts upload limits via ini or wp-config; frontend only.
    replaces:
      files:
        "/etc/php.d/04uploadsize.ini":
          content: upload_max_filesize=1000M

infrastructure_notes:
  - EC2 instance types, VPC, subnets, and security groups must be provisioned externally via Terraform or CloudFormation.
  - Plugin layer cannot manage SSH restrictions, mount targets, or ELB listener protocols.
  - For full parity, consider ECS or Kubernetes with WordPress container orchestration.

Localhost Docker Setup

wordpress_deployment_pipeline:
  localhost_setup:
    prerequisites:
      - Docker Desktop or Podman
      - Git
      - WP-CLI (optional for scripted setup)
    steps:
      - Clone WordPress project:
          command: git clone https://github.com/WordPress/WordPress.git my-site
      - Create local config:
          file: docker-compose.yml
          content: |
            version: '3.8'
            services:
              wordpress:
                image: wordpress:latest
                ports:
                  - "8080:80"
                environment:
                  WORDPRESS_DB_HOST: db
                  WORDPRESS_DB_USER: wp
                  WORDPRESS_DB_PASSWORD: wp
                  WORDPRESS_DB_NAME: wp
                volumes:
                  - ./wp-content:/var/www/html/wp-content
              db:
                image: mysql:5.7
                environment:
                  MYSQL_DATABASE: wp
                  MYSQL_USER: wp
                  MYSQL_PASSWORD: wp
                  MYSQL_ROOT_PASSWORD: root
      - Start containers:
          command: docker-compose up -d
      - Access site:
          url: http://localhost:8080

  dockerization:
    dockerfile:
      path: ./Dockerfile
      content: |
        FROM wordpress:latest
        COPY ./wp-content /var/www/html/wp-content
        RUN apt-get update && apt-get install -y amazon-efs-utils
        COPY ./mount-efs.sh /usr/local/bin/mount-efs.sh
        RUN chmod +x /usr/local/bin/mount-efs.sh
    build_command: docker build -t my-wordpress .
    notes: |
      - Ensure wp-content is modular and mountable
      - Use environment variables for secrets and branch context
      - Validate PHP-FPM config and upload limits

  circleci_deployment:
    prerequisites:
      - EC2 instance with SSH access
      - Docker installed on EC2
      - EFS or S3 configured for shared media
    circleci_config:
      path: .circleci/config.yml
      content: |
        version: 2.1
        jobs:
          build:
            docker:
              - image: cimg/base:stable
            steps:
              - checkout
              - setup_remote_docker
              - run:
                  name: Build Docker image
                  command: docker build -t my-wordpress .
              - run:
                  name: Save image
                  command: docker save my-wordpress | gzip > image.tar.gz
              - persist_to_workspace:
                  root: .
                  paths:
                    - image.tar.gz

          deploy:
            machine:
              enabled: true
            steps:
              - attach_workspace:
                  at: .
              - run:
                  name: Copy image to EC2
                  command: |
                    scp -i ~/.ssh/id_rsa image.tar.gz ec2-user@<EC2-IP>:/tmp/
              - run:
                  name: Load and run container on EC2
                  command: |
                    ssh -i ~/.ssh/id_rsa ec2-user@<EC2-IP> << EOF
                      docker load < /tmp/image.tar.gz
                      docker run -d -p 80:80 my-wordpress
                    EOF
    notes: |
      - Replace <EC2-IP> with your instance address
      - Ensure SSH key is added to CircleCI project settings
      - Validate EFS mount and PHP config post-deployment

References

https://hub.docker.com/r/serversideup/docker-ssh

https://docs.docker.com/engine/containers/resource_constraints/

https://github.com/golang/go/blob/master/src/crypto/tls/example_test.go

https://testdriven.io/blog/docker-best-practices/

https://blog.josefjebavy.cz/en/programming/docker-api-python

https://whaledeck.io/shorts/language/python/how-to-copy-files-to-a-docker-container

⚠️ **GitHub.com Fallback** ⚠️