etl/docs/source/docker.md
John Wellbelove 4a88884b39
Issue/add hugo support for documentation (#1449)
* Add ranges

* Initial Hugo setup

* Work in progress

* Added selection for local or remote site

* Updated to 'light' theme

* Changed to using Hextra Hugo theme

* Changed to using Hextra Hugo theme

* Changed to Hextra Hugo theme

* Change to Hextra Hugo theme

* Updated Hugo setup.

* Updated Hugo setup.

# Conflicts:
#	docs/releases/_index.md

* Work in progress

* Added new fonts

Added new documentation

* Latest documentation updates

* Latest documentation updates

# Conflicts:
#	docs/containers/array.md
#	docs/containers/array_view.md
#	docs/containers/array_wrapper.md
#	docs/containers/bip_buffer_spsc_atomic.md
#	docs/containers/bitset.md
#	docs/containers/indirect_vector.md
#	docs/containers/vector.md
#	docs/getting-started/compilers.md

* Added bloom_filter markdown doc

* Added more documentation

Updated CSS for light and dark modes

* Fixed some menus

Added mode documentation files

* Updated CSS rules

Added badges to home page
Added uniqur_ptr + pool tutorial

* Fixed formatting on the home page markdown

Modified light amd dark code formatting

* Updated unique_ptr-with-pool

* Added container and shared message tutorials

* Updates to documentation

* Added const_multimap

* Updated source-formatting.md

* Added initial raw text files form Web site editor

* Innore coverage build directory

* Exported raw text documentation files from the web site editor

* Hugo updates

* Added Hugo intalation and markdown descriptions

* More addition to the documentation

* Added closure.md and updates to delegate.md

* Added format.md

* Added documentation for etl::delegate_observable, etl::function, Base64 codec

* Added io_port documentation

* Added basic_format_spec

* Added documentation for string_stream and string utilities.

* Added more documentation

Updated the documentation CSS

* Added documentation for clocks, day, duration

* Added more documentation for chrono classes

Updated callouts

* More chrono documentation

* Completed chrono documentation

* Maths functions documentation

* Completed maths documentation

* Completed maths documentation

* Completed maths documentation

* Completed maths documentation

* Added multiple documentation files

* Added iterator.md

* Added debug_count.md and versions.md

* Added debug_count.md and versions.md

* Added more documentation

* More documentation

* Added some design pattern documentation

Modified some of the layout files
Modified the About documentation

* Converted more documentation pages

Modified the site CSS

* Added more documentation

Moced some documentation files to new directories

* Added more documentation

Tweaks to CSS

* Added callback_timer_deferred_locked documentation

* Added callback_timer_locked documentation

* More documentation updates

* More documentation updates

* More documentation updates

* New documentation files.

Harmonised file name format

* New documentation files.

* Multiple document updates

* Multiple document updates

* Final conversion of web pages

* Updates before PR

* Updates before PR

* Updates before PR

# Conflicts:
#	docs/blog/_index.md

* Final pre PR updates

* Updates to message framework documentation

* Renamed directory

* Fix spelling

* Added author and date to blog files

Moved documentation files merged from development

* Fixed 'Description' typo

* Fix typos

# Conflicts:
#	docs/IO/io_port.md
#	docs/containers/sets/const-multiset.md
#	docs/containers/sets/const-set.md
#	docs/maths/correlation.md
#	docs/maths/gamma.md

* Renamed two files to lower case

* Minor renaming

* Added author and date

* Updated callout on bresenham_line.md

Added support for showing the ETL version on the documentation first page, by copying the version.txt file as a hugo asset.
Updated the Python 'update_release.py' to copy 'version.txt'

* Replace space in filename with hyphen.

Added more information to hugo-commands.md

* Replace space in filename with hyphen.

Added more information to hugo-commands.md

# Conflicts:
#	docs/getting-started/view-the-docs-locally/hugo-commands.md

* Added a link to pseudo_moving_average.md

* Updated title pages for groups

* Fixed missing 404 for non-existent pages

* Fixed coordinate variable names in the 'Calculating the intersection' example

---------

Co-authored-by: Roland Reichwein <Roland.Reichwein@bmw.de>
Co-authored-by: John Wellbelove <john.wellbelove@etlcpp.com>
Co-authored-by: John Wellbelove <john.wellbelove@etlcpp.co.uk>
2026-06-06 13:12:44 +01:00

293 lines
9.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: "Docker for Development"
weight: 3
---
## Overview
The ETL repository ships a set of Docker-based development environments under
`.devcontainer/`. They give every contributor an identical, reproducible toolchain
regardless of host operating system. Three flavours are provided:
| Flavour | Path | Purpose |
|---|---|---|
| **Default** | `.devcontainer/` | Day-to-day development (Microsoft C++ dev-container base image) |
| **Compiler-specific** | `.devcontainer/gcc09/``.devcontainer/gcc15/`, `.devcontainer/clang7/``.devcontainer/clang21/` | Test against a specific GCC or Clang version |
| **s390x big-endian** | `.devcontainer/s390x/` | Cross-compile and run tests on an s390x target via QEMU |
All containers include CMake, Make, Git, Python 3, cogapp (the code generator used
by ETL), clang-format 18, and treefmt.
## Prerequisites
- **Docker** (or Docker Desktop) any recent version that supports `docker build`
and `docker run`.
- **VS Code** with the
[Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)
extension (optional, but recommended for the smoothest experience).
- **Git** to clone the repository.
## Quick Start
### Using the helper script
The fastest way to get a shell inside the default container from the project root:
```bash
./scripts/run-docker.sh
```
This script performs two steps:
1. **Builds** the image from `.devcontainer/Dockerfile` and tags it `etl`.
2. **Runs** an interactive container that bind-mounts the repository at
`/home/vscode/etl` so that edits made inside the container are visible on
the host (and vice versa).
You are dropped into a Bash shell as the `vscode` user with the working
directory set to the repository root.
### Using VS Code Dev Containers
1. Open the repository folder in VS Code.
2. When prompted, click **Reopen in Container** or run the command
*Dev Containers: Reopen in Container* from the command palette.
3. VS Code reads `.devcontainer/devcontainer.json`, builds the image, and
attaches to the running container automatically.
To open a **specific compiler variant** instead, run
*Dev Containers: Open Folder in Container…* and pick the sub-folder (e.g.
`.devcontainer/gcc14/`), or use the command palette action
*Dev Containers: Open Named Container Configuration…* and select the desired
name (e.g. "Gcc 14", "Clang 18").
## Default Development Container
The file `.devcontainer/Dockerfile` is a multi-purpose image used by the
default configuration **and** by every compiler-specific variant (they simply
override the `BASE_IMAGE_NAME` build argument).
### Base image
```text
mcr.microsoft.com/devcontainers/cpp:2
```
The exact digest is pinned in `devcontainer.json` so that builds are
reproducible even if the upstream tag is updated.
### Installed tools
The Dockerfile installs the following on top of the base image:
| Tool | Purpose |
|---|---|
| `python3`, `pip` | Runtime for helper scripts |
| `python3-cogapp` / `cogapp` | ETL code generator |
| `git` | Version control |
| `wget` | Downloading additional tooling |
| `cmake`, `make` | Build system |
| `clang-format` (v18) | Source formatting (see [source-formatting.md](source-formatting.md)) |
| `treefmt` (v2.4.1) | Single-command formatting wrapper |
### Reproducible builds with Debian snapshots
The default configuration sets the build argument
`DEBIAN_SNAPSHOT=20260223T000000Z`. When this value is not `"none"`, the
Dockerfile rewrites the APT sources to point at
`snapshot.debian.org/archive/debian/<timestamp>`, ensuring that every
contributor installs identical package versions. Compiler-specific variants
that are based on upstream `gcc:*` or `silkeh/clang:*` images set
`DEBIAN_SNAPSHOT=none` because those images manage their own package sources.
## Compiler-Specific Containers
Each sub-folder under `.devcontainer/` contains a `devcontainer.json` that
reuses the **same** `Dockerfile` (`../Dockerfile`) but overrides the
`BASE_IMAGE_NAME` build argument to select a different compiler.
### GCC variants
| Folder | Base image | Name |
|---|---|---|
| `gcc09/` | `gcc:9` | Gcc 09 |
| `gcc10/` | `gcc:10` | Gcc 10 |
| `gcc11/` | `gcc:11` | Gcc 11 |
| `gcc12/` | `gcc:12` | Gcc 12 |
| `gcc13/` | `gcc:13` | Gcc 13 |
| `gcc14/` | `gcc:14` | Gcc 14 |
| `gcc15/` | `gcc:15` | Gcc 15 |
### Clang variants
| Folder | Base image | Name |
|---|---|---|
| `clang7/` | `silkeh/clang:7` | Clang 7 |
| `clang8/` | `silkeh/clang:8` | Clang 8 |
| `clang9/` | `silkeh/clang:9` | Clang 9 |
| `clang10/` | `silkeh/clang:10` | Clang 10 |
| `clang11/` | `silkeh/clang:11` | Clang 11 |
| `clang12/` | `silkeh/clang:12` | Clang 12 |
| `clang13/` | `silkeh/clang:13` | Clang 13 |
| `clang14/` | `silkeh/clang:14` | Clang 14 |
| `clang15/` | `silkeh/clang:15` | Clang 15 |
| `clang16/` | `silkeh/clang:16` | Clang 16 |
| `clang17/` | `silkeh/clang:17` | Clang 17 |
| `clang18/` | `silkeh/clang:18` | Clang 18 |
| `clang19/` | `silkeh/clang:19` | Clang 19 |
| `clang20/` | `silkeh/clang:20` | Clang 20 |
| `clang21/` | `silkeh/clang:21` | Clang 21 |
All compiler-specific variants set `DEBIAN_SNAPSHOT` to `"none"` because they
rely on the upstream image's own package sources.
## s390x Big-Endian Cross-Compilation
The `s390x` container lives in `.devcontainer/s390x/` and has its **own**
Dockerfile (it does not reuse the default one). It is based on
`debian:trixie` and installs:
- QEMU user-mode emulation (`qemu-user-static`, `qemu-user`, `binfmt-support`)
- s390x cross-compilation toolchain (`gcc-s390x-linux-gnu`,
`g++-s390x-linux-gnu`)
- CMake, Make, Ninja, Git, wget
### Container setup
Open `.devcontainer/s390x/` as a Dev Container in VS Code, or build manually:
```bash
docker build -t etl-s390x .devcontainer/s390x
docker run -it --rm -v .:/workspaces/etl -w /workspaces/etl etl-s390x
```
### CMake toolchain
A CMake toolchain file is provided at
`.devcontainer/s390x/toolchain-s390x.cmake`. It sets:
- `CMAKE_SYSTEM_PROCESSOR` to `s390x`
- Cross-compilers `s390x-linux-gnu-gcc` / `g++`
- `CMAKE_CROSSCOMPILING_EMULATOR` to `/usr/bin/qemu-s390x-static`
The VS Code Dev Container configuration already passes this toolchain file
via `cmake.configureArgs`, so CMake Tools picks it up automatically.
### Running tests under QEMU
Because the toolchain file sets `CMAKE_CROSSCOMPILING_EMULATOR`, CTest
automatically invokes `qemu-s390x-static` when running test binaries.
No extra flags are needed:
```bash
cmake -S test -B build-s390x \
-DCMAKE_TOOLCHAIN_FILE=.devcontainer/s390x/toolchain-s390x.cmake \
-DBUILD_TESTS=ON -DNO_STL=OFF -DETL_CXX_STANDARD=17 -G Ninja
cmake --build build-s390x
ctest --test-dir build-s390x
```
## Building and Running Tests
Once inside any container (default, compiler-specific, or s390x) you can
build and run the ETL test suite.
### Quick CMake workflow
```bash
# Configure build tests with C++17
cmake -S test -B build -DBUILD_TESTS=ON -DETL_CXX_STANDARD=17
# Build
cmake --build build -j $(nproc)
# Run tests
ctest --test-dir build
```
Change `DETL_CXX_STANDARD` to `11`, `14`, `17`, `20`, or `23` as needed.
Add `-DNO_STL=ON` to build without the standard library.
### Using the run-tests script
The repository also provides a convenience script in `test/`:
```bash
cd test
./run-tests.sh <standard> [optimisation] [threads] [sanitizer] [compiler] [verbose]
```
| Argument | Values | Default |
|---|---|---|
| C++ standard | `11`, `14`, `17`, `20`, `23` | *(required)* |
| Optimisation | `0`, `1`, `2`, `3` | `0` |
| Threads | any integer | `4` |
| Sanitizer | `s` (enable) / `n` (disable) | `n` |
| Compiler | `gcc` / `clang` | all |
| Verbose | `v` (enable) / `n` (disable) | `n` |
Example run C++17 tests at `-O2` with 8 threads using GCC:
```bash
./run-tests.sh 17 2 8 n gcc n
```
## Formatting Inside the Container
The default container ships with **clang-format 18** and **treefmt**.
See [source-formatting.md](source-formatting.md) for the full formatting guide.
Quick reference:
```bash
# Format all tracked C/C++ files with treefmt
treefmt
# Or use clang-format directly via the wrapper
./scripts/clang-format-wrapper -i include/etl/*.h
```
The wrapper script `scripts/clang-format-wrapper` resolves the correct
clang-format binary (prefers `clang-format-18`, falls back to `clang-format`
after checking the major version).
## Customisation
To add extra packages or tools to the default container, edit
`.devcontainer/Dockerfile`. The image follows a straightforward
`apt-get install` pattern, so adding a new package is as simple as appending
it to the existing `apt-get` line.
To create a new compiler variant:
1. Create a folder under `.devcontainer/` (e.g. `.devcontainer/gcc16/`).
2. Add a `devcontainer.json` that references `"../Dockerfile"` and sets
`BASE_IMAGE_NAME` to the desired image (e.g. `gcc:16`).
3. Set `DEBIAN_SNAPSHOT` to `"none"` for upstream compiler images.
Example:
```jsonc
{
"name": "Gcc 16",
"build": {
"dockerfile": "../Dockerfile",
"args": {
"BASE_IMAGE_NAME": "gcc:16",
"DEBIAN_SNAPSHOT": "none"
},
"context": "../context"
}
}
```
## Troubleshooting
| Symptom | Cause / Fix |
|---|---|
| `apt-get` fails with *"Release file … is not valid yet"* | The Debian snapshot timestamp is in the future relative to the build host clock. Either update `DEBIAN_SNAPSHOT` in `devcontainer.json` or set it to `"none"`. |
| `clang-format` reports the wrong version | The wrapper expects version **18**. Make sure the image installs `clang-format` (or `clang-format-18`) and that the binary is on `PATH`. |
| Permission errors on mounted files | The `run-docker.sh` script runs as user `vscode`. Ensure your host UID matches, or adjust the `--user` flag. |
| s390x tests crash immediately | Verify that `qemu-user-static` is installed and that `binfmt-support` is active. On some hosts you may need to register binfmt handlers with `docker run --privileged --rm tonistiigi/binfmt --install all`. |
| Build is very slow the first time | Docker is downloading and building the image from scratch. Subsequent builds use the layer cache and are much faster. |