# Docker images

The Docker images femforge builds, the femforge-elmer solver image, and the environment probe that checks this machine can mesh and solve.

## femforge.execution.docker.image

Images femforge builds itself: apt install scripts from typed sections, version tags guarded by a recipe hash, and the build on first use.

Classes:

- **`AptPackage`** –

  An apt package an image installs and why it needs it.
- **`DockerImage`** –

  An image a tool runs in: a published or built recipe image, or with no recipe, a tag Docker has or pulls.
- **`ImageRecipe`** –

  An image femforge builds itself, with the version and recipe hash it was last released at.
- **`Section`** –

  One titled block of an install script, listing each package it installs with its reason.

Functions:

- **`apt_install`** –

  An `apt-get install` of `packages`, one per line.
- **`ensure_image`** –

  Make Docker hold `image`: reuse a matching local tag, else pull a published one, else build its recipe; checked once per tag per process.
- **`install_run`** –

  A Dockerfile `RUN` heredoc that runs `sections` as one strict, non-interactive shell script.

Attributes:

- **`REGISTRY`** –

  The registry namespace femforge publishes its released images under.

### REGISTRY

```python
REGISTRY = 'ghcr.io/femforge-io'
```

The registry namespace femforge publishes its released images under.

### AptPackage

```python
AptPackage(name: str, reason: str, build_only: bool = False)
```

An apt package an image installs and why it needs it.

Attributes:

- **`build_only`** (`bool`) –

  Whether the install purges the package once it is done with it.

#### build\_only

```python
build_only: bool = False
```

Whether the install purges the package once it is done with it.

### DockerImage

```python
DockerImage(tag: str, dockerfile: str | None = None, probe: tuple[str, ...] = (), published: bool = False, platform: str | None = None, labels: tuple[str, ...] = ())
```

An image a tool runs in: a published or built recipe image, or with no recipe, a tag Docker has or pulls.

Attributes:

- **`probe`** (`tuple[str, ...]`) –

  A command run in the fresh image whose output the build logs, such as the installed tool's version.
- **`published`** (`bool`) –

  Whether a registry serves the tag, so it is pulled before it is built.
- **`platform`** (`str | None`) –

  The platform the image is pulled, built and run for, such as `linux/amd64`; None lets Docker choose.
- **`labels`** (`tuple[str, ...]`) –

  The `KEY=VALUE` labels a build stamps beside the recipe label.
- **`platform_args`** (`list[str]`) –

  The `--platform` option of a docker command, empty without a platform.

#### probe

```python
probe: tuple[str, ...] = ()
```

A command run in the fresh image whose output the build logs, such as the installed tool's version.

#### published

```python
published: bool = False
```

Whether a registry serves the tag, so it is pulled before it is built.

#### platform

```python
platform: str | None = None
```

The platform the image is pulled, built and run for, such as `linux/amd64`; None lets Docker choose.

#### labels

```python
labels: tuple[str, ...] = ()
```

The `KEY=VALUE` labels a build stamps beside the recipe label.

#### platform\_args

```python
platform_args: list[str]
```

The `--platform` option of a docker command, empty without a platform.

### ImageRecipe

```python
ImageRecipe(name: str, version: str, digest: str, dockerfile: str, source: Path, probe: tuple[str, ...] = (), registry: str = REGISTRY, platform: str | None = None, probe_label: str = '')
```

An image femforge builds itself, with the version and recipe hash it was last released at.

Methods:

- **`image`** –

  The released image under the registry, or while the recipe differs from the released one, a local dev image that is never published.

Attributes:

- **`digest`** (`str`) –

  The sha256 of the Dockerfile released as `version`.
- **`source`** (`Path`) –

  The module whose `IMAGE_VERSION` and `IMAGE_DIGEST` lines a bump rewrites.
- **`registry`** (`str`) –

  The registry namespace a released version is published under.
- **`platform`** (`str | None`) –

  The platform the image is built for and runs on; None lets Docker choose.
- **`probe_label`** (`str`) –

  What `probe` reports the version of, such as `elmerfem-csc`.

#### digest

```python
digest: str
```

The sha256 of the Dockerfile released as `version`.

#### source

```python
source: Path
```

The module whose `IMAGE_VERSION` and `IMAGE_DIGEST` lines a bump rewrites.

#### registry

```python
registry: str = REGISTRY
```

The registry namespace a released version is published under.

#### platform

```python
platform: str | None = None
```

The platform the image is built for and runs on; None lets Docker choose.

#### probe\_label

```python
probe_label: str = ''
```

What `probe` reports the version of, such as `elmerfem-csc`.

#### image

```python
image() -> DockerImage
```

The released image under the registry, or while the recipe differs from the released one, a local dev image that is never published.

### Section

```python
Section(title: str, commands: tuple[str, ...], packages: tuple[AptPackage, ...] = ())
```

One titled block of an install script, listing each package it installs with its reason.

Methods:

- **`render`** –

  The block as shell lines: a dashed banner, the package reasons, then the commands.

#### render

```python
render() -> str
```

The block as shell lines: a dashed banner, the package reasons, then the commands.

### apt\_install

```python
apt_install(packages: tuple[AptPackage, ...]) -> str
```

An `apt-get install` of `packages`, one per line.

### ensure\_image

```python
ensure_image(image: DockerImage, docker: DockerCli, *, pull: bool = True) -> None
```

Make Docker hold `image`: reuse a matching local tag, else pull a published one, else build its recipe; checked once per tag per process.

A tag without a recipe is pulled when Docker lacks it and never built, so a failed pull raises `DockerError`.

Parameters:

- **`image`** (`DockerImage`) –

  The image to make available.
- **`docker`** (`DockerCli`) –

  The client to run Docker through.
- **`pull`** (`bool`, default: `True` ) –

  Try the registry before building a published recipe.

### install\_run

```python
install_run(sections: Sequence[Section]) -> str
```

A Dockerfile `RUN` heredoc that runs `sections` as one strict, non-interactive shell script.

## femforge.elmer.runtime.docker\_image

The femforge-elmer Docker image: headless Elmer from CSC's PPA on Ubuntu 24.04, with Open MPI and MUMPS.

Functions:

- **`dockerfile`** –

  The image's Dockerfile, generated from `INSTALL`.

Attributes:

- **`ELMER_IMAGE`** –

  The image Elmer runs in under the Docker backend.

### ELMER\_IMAGE

```python
ELMER_IMAGE = ImageRecipe(name='femforge-elmer', version=IMAGE_VERSION, digest=IMAGE_DIGEST, dockerfile=dockerfile(), source=Path(__file__), probe=('dpkg-query', '--show', '--showformat=${Version}', ELMER_PACKAGE.name), platform=PLATFORM, probe_label=ELMER_PACKAGE.name)
```

The image Elmer runs in under the Docker backend.

### dockerfile

```python
dockerfile() -> str
```

The image's Dockerfile, generated from `INSTALL`.

## femforge.doctor

`femforge doctor`: check that this machine can mesh and solve, and name the fix for whatever it cannot.

Classes:

- **`Check`** –

  One doctor check: what it looked at, how it went, and how to fix it.
- **`CheckName`** –

  The checks, in the order the doctor runs them.
- **`CheckStatus`** –

  How a check went.
- **`DoctorReport`** –

  Every doctor check in order, with the count of blockers and warnings.

Functions:

- **`add_arguments`** –

  The `femforge doctor` options.
- **`diagnose`** –

  Run every check against this machine.
- **`render`** –

  Print the checks as a table, then the numbered fixes and the count of blockers and warnings.
- **`run`** –

  Run the checks and report them; the exit code is 1 when any check failed.

Attributes:

- **`COMMAND`** –

  The `femforge` subcommand.

### COMMAND

```python
COMMAND = 'doctor'
```

The `femforge` subcommand.

### Check

Bases: `BaseModel`

One doctor check: what it looked at, how it went, and how to fix it.

Config:

- `use_attribute_docstrings`: `True`

Fields:

- `name` (`CheckName`)
- `status` (`CheckStatus`)
- `detail` (`str`)
- `fix` (`str | None`)

#### name

```python
name: CheckName
```

What was checked.

#### status

```python
status: CheckStatus
```

How the check went.

#### detail

```python
detail: str
```

What the check found.

#### fix

```python
fix: str | None = None
```

What to do about it, when there is something to do.

### CheckName

Bases: `StrEnum`

The checks, in the order the doctor runs them.

### CheckStatus

Bases: `StrEnum`

How a check went.

Attributes:

- **`style`** (`str`) –

  The Rich style the status shows in.

#### style

```python
style: str
```

The Rich style the status shows in.

### DoctorReport

Bases: `BaseModel`

Every doctor check in order, with the count of blockers and warnings.

Config:

- `use_attribute_docstrings`: `True`
- `json_schema_mode_override`: `serialization`

Fields:

- `checks` (`list[Check]`)

#### checks

```python
checks: list[Check]
```

The checks, in the order they ran.

#### blockers

```python
blockers: int
```

How many checks failed.

#### warnings

```python
warnings: int
```

How many checks warned.

### add\_arguments

```python
add_arguments(parser: ArgumentParser) -> None
```

The `femforge doctor` options.

### diagnose

```python
diagnose(runs_dir: Path, artifacts: Path | None = None, *, docker: DockerCli | None = None, recipe: ImageRecipe = ELMER_IMAGE) -> DoctorReport
```

Run every check against this machine.

Parameters:

- **`runs_dir`** (`Path`) –

  The runs directory whose disk is checked.
- **`artifacts`** (`Path | None`, default: `None` ) –

  The artifact store whose disk is checked; None skips that check.
- **`docker`** (`DockerCli | None`, default: `None` ) –

  The Docker client to probe through; None makes one.
- **`recipe`** (`ImageRecipe`, default: `ELMER_IMAGE` ) –

  The image recipe whose image is checked.

### render

```python
render(report: DoctorReport, console: Console) -> None
```

Print the checks as a table, then the numbered fixes and the count of blockers and warnings.

### run

```python
run(args: Namespace, console: Console, artifacts: str | None) -> int
```

Run the checks and report them; the exit code is 1 when any check failed.

Parameters:

- **`args`** (`Namespace`) –

  The parsed `femforge doctor` options.
- **`console`** (`Console`) –

  Where the table goes.
- **`artifacts`** (`str | None`) –

  The artifact store root from the environment, or None.
