Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
c93f3f3
build(devcontainer): add development container setup
kadykov Oct 27, 2025
c2ee361
Merge branch 'darktable-org:master' into devcontainer
kadykov Nov 8, 2025
196a090
Merge branch 'darktable-org:master' into devcontainer
kadykov Jan 9, 2026
1908f7f
Merge branch 'darktable-org:master' into devcontainer
kadykov Mar 11, 2026
8582a3b
Remove apt cache in the container
kadykov Mar 13, 2026
505cf46
Merge branch 'darktable-org:master' into devcontainer
kadykov May 14, 2026
fe0fbbd
Merge branch 'darktable-org:master' into devcontainer
kadykov Jul 15, 2026
9dc1426
Merge branch 'darktable-org:master' into devcontainer
kadykov Aug 15, 2026
3dc0a80
Add devcontainer-lock.json for common-utils feature configuration
kadykov Aug 15, 2026
4eca62a
Add additional dependencies for image processing and tools in Dockerfile
kadykov Aug 15, 2026
f6d62f3
Align development container with CI environment by updating base imag…
kadykov Aug 15, 2026
a9019c5
Update README to clarify devcontainer purpose and prerequisites, enha…
kadykov Aug 15, 2026
a9123e5
Remove clang-format extension from VSCode settings in devcontainer co…
kadykov Aug 16, 2026
9ae2189
Rewrite dev container README, reference container-based build environ…
kadykov Aug 16, 2026
5eef79e
Enhance README with Docker and Podman installation instructions for c…
kadykov Aug 16, 2026
b28e9de
Add GitHub Actions workflow to build and publish Docker image
kadykov Aug 19, 2026
f034ea4
Update README to merge tier 2 and 3, add dev container installation i…
kadykov Aug 19, 2026
8dedc1d
Merge branch 'darktable-org:master' into devcontainer
kadykov Aug 19, 2026
6f54f8b
Update Dockerfile to speed up installation with eatmydata and add mis…
kadykov Aug 19, 2026
a2635b9
Add packages for AppImage building and OpenCL support in Dockerfile
kadykov Aug 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 120 additions & 0 deletions .devcontainer/Dockerfile
Comment thread
kadykov marked this conversation as resolved.
Comment thread
kadykov marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# Use Ubuntu 26.04 LTS to match the CI environment
# CI uses ubuntu:26.04 container in .github/workflows/ci.yml
FROM ubuntu:26.04

# Avoid prompts from apt
ENV DEBIAN_FRONTEND=noninteractive

# Set up locale
RUN apt-get update && apt-get install -y locales && \
locale-gen en_US.UTF-8 && \
update-locale LANG=en_US.UTF-8 && \
rm -rf /var/lib/apt/lists/*

ENV LANG=en_US.UTF-8
ENV LANGUAGE=en_US:en
ENV LC_ALL=en_US.UTF-8

# Match the CI "Update base packages" step
RUN apt-get update && apt-get install -y eatmydata && \
eatmydata apt-get --yes upgrade && \
rm -rf /var/lib/apt/lists/*

# Install compilers matching CI:
# - Primary: GNU16 (gcc-16 / g++-16)
# - Alternative: LLVM22 (clang-22 / clang++-22)
RUN eatmydata apt-get update && eatmydata apt-get --yes install \
gcc-16 \
g++-16 \
clang-22 \
libomp-22-dev \
llvm-22-dev \
libc++-22-dev \
libc++abi1 \
lld-22 \
clang-tools-22 \
mlir-22-tools \
libmlir-22-dev \
&& rm -rf /var/lib/apt/lists/*

# Install base dependencies — exact match with CI
# (see "Install Base Dependencies" step in .github/workflows/ci.yml)
RUN eatmydata apt-get update && eatmydata apt-get --yes install \
build-essential \
cmake \
appstream-util \
desktop-file-utils \
gettext \
git \
gdb \
intltool \
libarchive-dev \
libatk1.0-dev \
libavif-dev \
libcairo2-dev \
libcmocka-dev \
libcolord-dev \
libcolord-gtk-dev \
libcups2-dev \
libcurl4-gnutls-dev \
libexiv2-dev \
libgdk-pixbuf-2.0-dev \
libglib2.0-dev \
libgmic-dev \
libgphoto2-dev \
libgraphicsmagick1-dev \
libgtk-3-dev \
libheif-dev \
libjpeg-dev \
libjson-glib-dev \
liblcms2-dev \
liblensfun-dev \
liblua5.4-dev \
libonnxruntime-dev \
libopencv-calib3d-dev \
libopencv-core-dev \
libopencv-features2d-dev \
libopencv-flann-dev \
libopencv-imgproc-dev \
libopenexr-dev \
libopenjp2-7-dev \
libosmgpsmap-1.0-dev \
libpango1.0-dev \
libpng-dev \
libportmidi-dev \
libpotrace-dev \
libpugixml-dev \
libraw-dev \
librsvg2-dev \
libsaxon-java \
libsdl2-dev \
libsecret-1-dev \
libsqlite3-dev \
libtiff5-dev \
libwebp-dev \
libx11-dev \
libxml2-dev \
libxml2-utils \
ninja-build \
perl \
po4a \
python3-jsonschema \
xsltproc \
zlib1g-dev \
&& rm -rf /var/lib/apt/lists/*

# Install packages useful for building AppImages for GUI testing on host machine
# TODO: Remove this layer once we have a dedicated AppImage container
RUN eatmydata apt-get update && eatmydata apt-get --yes install \
# Required for building AppImages
wget \
# OpenCL support (optional GPU acceleration)
ocl-icd-opencl-dev \
# JXL image format
libjxl-dev \
&& rm -rf /var/lib/apt/lists/*

# Set the working directory
WORKDIR /workspace

CMD ["/bin/bash"]
232 changes: 232 additions & 0 deletions .devcontainer/README.md
Comment thread
kadykov marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
# Darktable Container Build Environment

A Docker/Podman image that **exactly mirrors the CI compile check**, with all
build dependencies pre-installed. It is an **optional** complement to building
natively — every contributor can continue using their own environment as before.

## Use cases

- **Immutable/atomic Linux** (Fedora Silverblue, NixOS, SteamOS, etc.): avoids
installing and layering 50+ build packages that break on weekly OS rebuilds.
- **Infrequent contributors**: get a working build environment without a
permanent setup.
- **Reproducing CI failures**: your local environment matches the CI container
exactly, so a build that passes here passes CI.
- **Sandboxing AI coding agents**: tools running inside the container can only
access the mounted workspace — host SSH keys, credentials, private documents,
and other projects remain invisible to them.

## Prerequisites: Docker or Podman

Docker (or Podman) is required for all usage options below. Install one:

| Platform | Command / link |
| -------- | -------------- |
| Debian / Ubuntu | `sudo apt install docker.io` or [Docker CE](https://docs.docker.com/engine/install/ubuntu/) (recommended — includes BuildKit) |
| Fedora / RHEL | `sudo dnf install docker` or [Docker CE](https://docs.docker.com/engine/install/fedora/) |
| Arch | `sudo pacman -S docker` |
| openSUSE | `sudo zypper install docker` |
| macOS | `brew install --cask docker` or `brew install podman` |
| Windows | [Docker Desktop](https://docs.docker.com/desktop/setup/install/windows-install/) |

On Linux, add your user to the `docker` group and log out/in before using it:

```bash
sudo usermod -aG docker "$USER"
```

**Podman** is a rootless drop-in replacement on Linux (`alias docker=podman`).
See the [Podman installation guide](https://podman.io/docs/installation).

## Option 1: Docker/Podman CLI (most lightweight)

No IDE, no extra tooling — just build and run the container directly.

```bash
# Build the image once (from the repository root)
docker build -t darktable-dev -f .devcontainer/Dockerfile .
Comment thread
kadykov marked this conversation as resolved.

# Verify the build compiles (same environment as CI)
docker run --rm --user "$(id -u):$(id -g)" \
-v "$PWD":/workspace -w /workspace \
darktable-dev \
bash -lc './build.sh --prefix /tmp/dt --build-type Release'

# Build an AppImage for GUI testing on the host
docker run --rm --user "$(id -u):$(id -g)" \
-v "$PWD":/workspace -w /workspace \
-e APPIMAGE_EXTRACT_AND_RUN=1 \
darktable-dev \
bash -lc './tools/appimage-build-script.sh'
```

The AppImage appears in `build/Darktable-*.AppImage` and can be run on the host.

> Replace `docker` with `podman` if you use Podman.

## Option 2: Dev Container (richest experience)

A [Dev Container](https://containers.dev/) adds IDE integration on top of the
same Docker image: editor extensions, CMake integration, debugger support, etc.

### VS Code

Install the [Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers),
then open this repository and click **"Reopen in Container"** when prompted
(or F1 → *Dev Containers: Reopen in Container*). Git submodules are initialized
automatically.

### JetBrains IDEs (CLion, etc.)

Install the Dev Containers plugin and follow the
[JetBrains Dev Containers guide](https://www.jetbrains.com/help/idea/connect-to-devcontainer.html).

### Other editors and terminal

Install the [`devcontainer` CLI](https://github.com/devcontainers/cli):

```bash
npm install -g @devcontainers/cli
```

Then:

```bash
# Start the container
devcontainer up --workspace-folder .

# Open a shell
devcontainer exec --workspace-folder . bash
```

> **VS Code and JetBrains bundle their own devcontainer implementation** — you
> only need to install the CLI separately when using other editors or working
> purely in a terminal.

The VS Code extensions listed in [`devcontainer.json`](devcontainer.json) are
all from Microsoft (`ms-vscode.*`) or well-established publishers.

## Building darktable

Inside the container (any option):

```bash
# Standard development build
./build.sh --prefix /tmp/dt --build-type RelWithDebInfo

# Debug build
./build.sh --prefix /tmp/dt --build-type Debug

# Switch to Clang 22 (matches CI LLVM22 path)
export CC=clang-22 CXX=clang++-22
./build.sh --prefix /tmp/dt --build-type RelWithDebInfo
```

## Testing with AppImage

The container has no display. GUI testing uses an AppImage built inside the
container and run on the host.

```bash
# APPIMAGE_EXTRACT_AND_RUN=1 is required — FUSE is not available in containers
APPIMAGE_EXTRACT_AND_RUN=1 ./tools/appimage-build-script.sh
```

The AppImage is created in `build/Darktable-*.AppImage`. Run it on the host:

```bash
chmod +x build/Darktable-*.AppImage
./build/Darktable-*.AppImage --configdir ~/.config/darktable-test
```

Using `--configdir` avoids touching your production darktable configuration.

## Running unit tests

`libcmocka-dev` is already installed:

```bash
./build.sh --prefix /tmp/dt --build-type RelWithDebInfo -- -DBUILD_TESTING=ON
cd build && ctest
```

## CI environment and pre-built images

The [Dockerfile](Dockerfile) is the single source of truth for the build
environment. Inspect it for the exact base image, compiler versions, and
package list.

### Pre-built images on GHCR

`.github/workflows/build-docker.yml` automatically builds the image and
publishes it to the GitHub Container Registry (GHCR) whenever the `Dockerfile`
changes on the `master` branch. The pre-built image is available at:

```
ghcr.io/darktable-org/darktable-build:latest
```

Using the pre-built image skips the local build step:

```bash
docker pull ghcr.io/darktable-org/darktable-build:latest
docker run --rm --user "$(id -u):$(id -g)" \
-v "$PWD":/workspace -w /workspace \
ghcr.io/darktable-org/darktable-build:latest \
bash -lc './build.sh --prefix /tmp/dt --build-type Release'
```

## Troubleshooting

### `docker build` prints a deprecation warning about the legacy builder

This happens with older Docker installations (e.g. Ubuntu's `docker.io` package)
that don't use BuildKit by default. Fix by installing Docker CE via the
[official Docker Engine docs](https://docs.docker.com/engine/install/ubuntu/)
(which includes `docker-buildx-plugin`), or just add the plugin to an existing
installation:

```bash
sudo apt install docker-buildx-plugin
```

### AppImage build fails with FUSE error

Always set `APPIMAGE_EXTRACT_AND_RUN=1` — FUSE is not available inside containers.

### Git submodules not initialized

```bash
git submodule update --init --recursive
```

### Git says the repository has dubious ownership inside the container

Pass `--user "$(id -u):$(id -g)"` to `docker run` (as shown in the examples
above), or mark the path as safe inside the container:

```bash
git config --global --add safe.directory /workspace
```

### Need to install an extra package temporarily

```bash
sudo apt-get update && sudo apt-get install <package>
```

### Rebuild the container after Dockerfile changes

VS Code: F1 → *Dev Containers: Rebuild Container*
CLI: `devcontainer up --workspace-folder . --remove-existing-container`

## File structure

```text
.devcontainer/
├── Dockerfile # Build environment (mirrors CI)
├── devcontainer.json # IDE/tooling configuration
└── README.md # This file
.github/workflows/
└── build-docker.yml # Publishes the image to GHCR on Dockerfile changes
```
9 changes: 9 additions & 0 deletions .devcontainer/devcontainer-lock.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"features": {
"ghcr.io/devcontainers/features/common-utils:2": {
"version": "2.5.9",
"resolved": "ghcr.io/devcontainers/features/common-utils@sha256:cb0c4d3c276f157eed17935747e364178d75fee17f55c4e129966f64633deb3a",
"integrity": "sha256:cb0c4d3c276f157eed17935747e364178d75fee17f55c4e129966f64633deb3a"
}
}
}
32 changes: 32 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "Darktable Development",
"build": {
"dockerfile": "Dockerfile",
"context": ".."
},
"runArgs": [
"--cap-add=SYS_PTRACE",
"--security-opt=seccomp=unconfined"
],
"features": {
"ghcr.io/devcontainers/features/common-utils:2": {
"username": "vscode"
}
},
"customizations": {
"vscode": {
"extensions": [
"ms-vscode.cpptools",
"ms-vscode.cmake-tools",
"ms-vscode.cpptools-extension-pack"
],
"settings": {
"cmake.configureOnOpen": false,
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools"
}
}
},
"forwardPorts": [],
"postCreateCommand": "git submodule init && git submodule update && echo 'Development environment ready! See .devcontainer/README.md for build instructions.'",
"remoteUser": "vscode"
}
Loading
Loading