-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: useradd and pre-commit partials; root bake
- Loading branch information
Showing
6 changed files
with
346 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,211 @@ | ||
# dockerfile_partials | ||
Dockerfile partials for re-use across multiple applications | ||
# dockerfile-partials | ||
|
||
Dockerfile partials and devcontainer [bake](https://docs.docker.com/build/bake/introduction/) files for re-use across multiple applications. | ||
|
||
## Devcontainer bake files | ||
|
||
Each Dockerfile partial is accompanied by a `devcontainer-bake.hcl` [bake](https://docs.docker.com/build/bake/introduction/) config file, and a common bake file is defined at the repository root. These are intended to make composition of devcontainer image contents trivial. They are designed to work with the [devcontainer-cache-build initialize script](https://github.com/rcwbr/devcontainer-cache-build/tree/main?tab=readme-ov-file#initialize-script). | ||
|
||
Using these bake files remotely requires setting the primary build context to this repo by [remote definition](https://docs.docker.com/build/bake/remote-definition/). Because of [this limitation of remote bake build contexts](https://github.com/docker/buildx/blob/056cf8a7ca083d91eccf9200e7e2c99ff170bbaf/bake/bake.go#L1213C6-L1213C73) | ||
|
||
> ```We don't currently support reading a remote Dockerfile with a local context when doing a remote invocation because we automatically derive the dockerfile from the context atm``` | ||
this means that any build contexts required by the Dockerfile partial must be provided via a [local directory `contexts` context](https://docs.docker.com/build/bake/reference/#targetcontexts) rather than the primary build context. For example, the `pre-commit` Dockerfile [reads from the `local_context` context](https://github.com/rcwbr/dockerfile-partials/blob/086902fb92beb8ab2bf887ff6a6a141804762eb9/pre-commit/Dockerfile#L10C26-L10C39) [set to `BAKE_CMD_CONTEXT`](https://github.com/rcwbr/dockerfile-partials/blob/086902fb92beb8ab2bf887ff6a6a141804762eb9/pre-commit/devcontainer-bake.hcl#L11). This allows it to consume contents of the downstream build context. | ||
|
||
### Devcontainer bake files devcontainer-cache-build usage | ||
|
||
In a `devcontainer.json` leveraging the [devcontainer-cache-build initialize script](https://github.com/rcwbr/devcontainer-cache-build/tree/main?tab=readme-ov-file#initialize-script), add the following configuration to the `initializeCommand` before the `curl` to the initialize script: | ||
|
||
#### Devcontainer bake files devcontainer-cache-build initializeCommand config | ||
|
||
```json5 | ||
... | ||
"initializeCommand": [ | ||
... | ||
"export DEVCONTAINER_DEFINITION_TYPE=bake", | ||
"&& export DEVCONTAINER_DEFINITION_FILES=\"devcontainer-bake.hcl [path to each desired partial bake file] cwd://.devcontainer/devcontainer-bake.hcl\"", | ||
"&& export DEVCONTAINER_BUILD_ADDITIONAL_ARGS=https://github.com/rcwbr/dockerfile-partials.git#0.1.0", | ||
... | ||
] | ||
... | ||
``` | ||
|
||
`DEVCONTAINER_DEFINITION_FILES` must begin with `devcontainer-bake.hcl` and end with `cwd://.devcontainer/devcontainer-bake.hcl` (see [Devcontainer bake files devcontainer-cache-build .devcontainer/devcontainer-bake.hcl config](#devcontainer-bake-files-devcontainer-cache-build-devcontainerdevcontainer-bakehcl-config), and with each desired partial bake file in between (ordering is important for override priority). For example: | ||
|
||
```bash | ||
export DEVCONTAINER_DEFINITION_FILES=\"devcontainer-bake.hcl useradd/devcontainer-bake.hcl pre-commit/devcontainer-bake.hcl cwd://.devcontainer/devcontainer-bake.hcl\"" | ||
``` | ||
#### Devcontainer bake files devcontainer-cache-build .devcontainer/devcontainer-bake.hcl config | ||
To join the devcontainer partial bake files, you must define a bake file local to your project that configures targets from each partial you select. It must define at least the `devcontainer_layers` variable as a list with the names of each selected partial, and override the `base_context` for at least the first partial target. For example: | ||
```hcl | ||
variable "devcontainer_layers" { | ||
default = [ | ||
"useradd", | ||
"pre-commit" | ||
] | ||
} | ||
target "useradd" { | ||
contexts = { | ||
base_context = "docker-image://python:3.12.4" | ||
} | ||
} | ||
``` | ||
Optionally, `target`s may be configured for each layer. Values provided to these will override those defined in the partials `devcontainer-bake.hcl`. | ||
### Devcontainer bake files direct usage | ||
The partial bake files may be used manually through a command like this: | ||
```bash | ||
docker buildx bake --file devcontainer-bake.hcl [--file arg for each desired partial bake file] --file cwd://.devcontainer/devcontainer-bake.hcl https://github.com/rcwbr/dockerfile-partials.git#0.1.0 | ||
``` | ||
## Dockerfile partials | ||
### pre-commit | ||
The pre-commit Dockerfile defines steps to install [pre-commit](https://pre-commit.com/) and install the hooks required by a repo configuration. | ||
#### pre-commit Dockerfile usage | ||
The recommended usage is via the [Devcontainer bake files](#devcontainer-bake-files). It is also possible to use the Dockerfile partial directly. | ||
Use a [Bake](https://docs.docker.com/reference/cli/docker/buildx/bake/) config file, and set the `base_context` context as the image to which to apply the pre-commit installation, and the `local_context` to the directory from which the `.pre-commit-config.yaml` can be loaded (generally [`BAKE_CMD_CONTEXT`](https://docs.docker.com/build/bake/reference/#built-in-variables)). Additionally, provide appropriate values for the `USER` build arg. For example: | ||
```hcl | ||
target "base" { | ||
dockerfile = "Dockerfile" | ||
} | ||
target "default" { | ||
context = "https://github.com/rcwbr/dockerfile_partials.git#0.1.0" | ||
dockerfile = "pre-commit/Dockerfile" | ||
contexts = { | ||
base_context = "target:base" | ||
local_context = BAKE_CMD_CONTEXT | ||
} | ||
args = { | ||
USER = "myuser" | ||
} | ||
} | ||
``` | ||
The args accepted by the Dockerfile include: | ||
| Variable | Required | Default | Effect | | ||
| --- | --- | --- | --- | | ||
| `USER` | ✗ | `"root"` | Username to assume for hook pre-loading | | ||
#### pre-commit bake file usage | ||
The pre-commit partial contains a devcontainer bake config file. See [Devcontainer bake files](#devcontainer-bake-files) for general usage. The pre-commit bake config file accepts the following inputs: | ||
| Variable | Required | Default | Effect | | ||
| --- | --- | --- | --- | | ||
| `USER` | ✗ | `"root"` | See [pre-commit Dockerfile](#pre-commit-dockerfile-usage) | | ||
#### Codespaces usage | ||
For use in [Codespaces](https://github.com/features/codespaces) devcontainers, the build args must be set to the following values: | ||
- `USER`: `codespace` | ||
These values may be hard-coded in the Bake config file, or may be exposed as variables for compatibility with local environments. | ||
```hcl | ||
variable "USER" { | ||
default = "root" | ||
} | ||
... | ||
args = { | ||
USERNAME = "${USER}" | ||
} | ||
... | ||
``` | ||
If exposed as variables, the appropriate values for Codespaces use must be [set as secrets](https://docs.github.com/en/codespaces/managing-your-codespaces/managing-your-account-specific-secrets-for-github-codespaces#adding-a-secret) so as to be available during Codespace provisioning. | ||
### useradd | ||
The useradd Dockerfile defines steps to add a user to the image, with configurable user name, id, and group id. | ||
#### useradd Dockerfile usage | ||
The recommended usage is via the [Devcontainer bake files](#devcontainer-bake-files). It is also possible to use the Dockerfile partial directly. | ||
Use a [Bake](https://docs.docker.com/reference/cli/docker/buildx/bake/) config file, and set the `base_context` context as the image to which to apply the user addition. Additionally, provide appropriate values for the `USERNAME`, `USER_UID`, and `USER_GID` build args. For example: | ||
```hcl | ||
target "base" { | ||
dockerfile = "Dockerfile" | ||
} | ||
target "default" { | ||
context = "https://github.com/rcwbr/dockerfile_partials.git#0.1.0" | ||
dockerfile = "useradd/Dockerfile" | ||
contexts = { | ||
base_context = "target:base" | ||
} | ||
args = { | ||
USERNAME = "myuser" | ||
USER_UID = 1000 | ||
USER_GID = 1000 | ||
} | ||
} | ||
``` | ||
The args accepted by the Dockerfile include: | ||
| Variable | Required | Default | Effect | | ||
| --- | --- | --- | --- | | ||
| `USERNAME` | ✓ | N/A | Username of the user to create | | ||
| `USER_UID` | ✗ | `1000` | User UID for the user to create | | ||
| `USER_GID` | ✗ | `$USER_UID` | User GID for the user to create | | ||
#### useradd bake file usage | ||
The useradd partial contains a devcontainer bake config file. See [Devcontainer bake files](#devcontainer-bake-files) for general usage. The useradd bake config file accepts the following inputs: | ||
| Variable | Required | Default | Effect | | ||
| --- | --- | --- | --- | | ||
| `USER` | ✗ | `"root"` | See [useradd Dockerfile](#useradd-dockerfile-usage) | | ||
| `UID` | ✗ | `0` | See [useradd Dockerfile](#useradd-dockerfile-usage) | | ||
| `GID` | ✗ | `${UID}` | See [useradd Dockerfile](#useradd-dockerfile-usage) | | ||
#### useradd Codespaces usage | ||
For use in [Codespaces](https://github.com/features/codespaces) devcontainers, the build args must be set to the following values: | ||
- `USERNAME`: `codespace` | ||
- `USER_UID`: `1000` | ||
- `USER_GID`: `1000` | ||
These values may be hard-coded in the Bake config file, or may be exposed as variables for compatibility with local environments. | ||
```hcl | ||
variable "USER" { | ||
default = "root" | ||
} | ||
variable "UID" { | ||
default = 0 | ||
} | ||
variable "GID" { | ||
// Use the user id as group id unless set | ||
default = "${UID}" | ||
} | ||
... | ||
args = { | ||
USERNAME = "${USER}" | ||
USER_UID = "${UID}" | ||
USER_GID = "${GID}" | ||
} | ||
... | ||
``` | ||
If exposed as variables, the appropriate values for Codespaces use must be [set as secrets](https://docs.github.com/en/codespaces/managing-your-codespaces/managing-your-account-specific-secrets-for-github-codespaces#adding-a-secret) so as to be available during Codespace provisioning. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
// This file prepares only basic target configurations, handling the default base_contexts and output. | ||
// All other config for a target must be overridden by accompanying bake files. | ||
// It also configures a default group with each target listed. | ||
|
||
variable "DEVCONTAINER_CACHE_FROMS" { | ||
default = "" | ||
} | ||
variable "DEVCONTAINER_CACHE_TOS" { | ||
default = "" | ||
} | ||
variable "DEVCONTAINER_OUTPUTS" { | ||
default = "" | ||
} | ||
|
||
target "layer" { | ||
name = "${layer.name}" | ||
matrix = { | ||
layer = [ | ||
for index, input_layer in devcontainer_layers: { | ||
name = input_layer, | ||
index = index | ||
} | ||
] | ||
} | ||
|
||
// Apply the contexts from options and context | ||
contexts = { // Establish default base_context from layer order | ||
base_context = ( | ||
// A default base_context can be inferred only for the second layer and later | ||
layer.index >= 1 | ||
? "target:${element(devcontainer_layers, layer.index - 1)}" | ||
: "no_base_context_provided" | ||
) | ||
} | ||
|
||
// Apply cache args from the devcontainer context | ||
cache-from = [ | ||
for cache_from in split(" ", trimspace("${DEVCONTAINER_CACHE_FROMS}")): | ||
"${cache_from}-${layer.name}" | ||
] | ||
cache-to = [ | ||
for cache_to in split(" ", trimspace("${DEVCONTAINER_CACHE_TOS}")): | ||
"${cache_to}-${layer.name}" | ||
] | ||
|
||
// Apply the default output to the final layer | ||
output = ( | ||
layer.index == length(devcontainer_layers) - 1 | ||
? split(" ", trimspace("${DEVCONTAINER_OUTPUTS}")) | ||
: null | ||
) | ||
} | ||
|
||
group "default" { | ||
// Target the last layer as default | ||
targets = [devcontainer_layers[length(devcontainer_layers) - 1]] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# Set base_context in the downstream Bake file | ||
FROM base_context | ||
ARG USER=root | ||
USER root | ||
# Install git to spoof pre-commit environment | ||
RUN DEBIAN_FRONTEND=noninteractive \ | ||
apt-get update \ | ||
&& apt-get install --allow-unauthenticated --no-install-recommends -y \ | ||
git \ | ||
&& rm -rf /var/lib/apt/lists/* | ||
# Assume root role for installs | ||
USER ${USER} | ||
SHELL [ "/bin/bash", "-c" ] | ||
# Create a temp repo and install the hooks from the config | ||
# Load the config file from the downstream context | ||
RUN \ | ||
--mount=type=bind,from=local_context,source=.pre-commit-config.yaml,target=/tmp/.pre-commit-config.yaml \ | ||
python -m venv $HOME/pre-commit-venv \ | ||
&& source $HOME/pre-commit-venv/bin/activate \ | ||
&& mkdir $HOME/tmp_repo \ | ||
&& cd $HOME/tmp_repo \ | ||
&& cp /tmp/.pre-commit-config.yaml . \ | ||
&& git init . \ | ||
&& pip install pre-commit \ | ||
&& pre-commit install-hooks |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
variable "USER" { | ||
default = "root" | ||
} | ||
|
||
target "pre-commit" { | ||
dockerfile = "pre-commit/Dockerfile" | ||
contexts = { | ||
local_context = BAKE_CMD_CONTEXT | ||
} | ||
args = { | ||
USER = "${USER}" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Set base_context in the downstream Bake file | ||
FROM base_context AS base | ||
|
||
# Sourced from https://code.visualstudio.com/remote/advancedcontainers/add-nonroot-user | ||
ARG USERNAME= | ||
ARG USER_UID=1000 | ||
ARG USER_GID=$USER_UID | ||
|
||
# Create the user | ||
RUN groupadd --gid $USER_GID $USERNAME \ | ||
&& useradd --uid $USER_UID --gid $USER_GID -m $USERNAME \ | ||
# | ||
# [Optional] Add sudo support. Omit if you don't need to install software after connecting. | ||
&& apt-get update \ | ||
&& apt-get install -y sudo \ | ||
&& echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \ | ||
&& chmod 0440 /etc/sudoers.d/$USERNAME | ||
|
||
# Make use of the USER directive optional via target | ||
FROM base AS with_user | ||
USER $USERNAME |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
variable "USER" { | ||
default = "root" | ||
} | ||
variable "UID" { | ||
default = 0 | ||
} | ||
variable "GID" { | ||
// Use the user id as group id unless set | ||
default = "${UID}" | ||
} | ||
|
||
target "useradd" { | ||
dockerfile = "useradd/Dockerfile" | ||
args = { | ||
USERNAME = "${USER}" | ||
USER_UID = "${UID}" | ||
USER_GID = "${GID}" | ||
} | ||
} |