forked from TrueCloudLab/action-env
Compare commits
No commits in common. "empty" and "master" have entirely different histories.
19 changed files with 305 additions and 2 deletions
44
.forgejo/workflows/build.yml
Normal file
44
.forgejo/workflows/build.yml
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: build-${{matrix.tag}}
|
||||||
|
runs-on: docker
|
||||||
|
container: git.frostfs.info/truecloudlab/env:oci-image-builder-bookworm
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
tag:
|
||||||
|
- dotnet-8.0
|
||||||
|
- oci-image-builder-bookworm
|
||||||
|
- oci-runner
|
||||||
|
- openjdk-11-maven-3.8.6
|
||||||
|
- python-3.11
|
||||||
|
- python-3.13
|
||||||
|
steps:
|
||||||
|
- name: Clone git repo
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: List modified files
|
||||||
|
uses: actions/changed-files@v45
|
||||||
|
with:
|
||||||
|
files: |
|
||||||
|
${{matrix.tag}}/**
|
||||||
|
id: changed
|
||||||
|
|
||||||
|
- name: Build OCI image
|
||||||
|
run: make ${{matrix.tag}}
|
||||||
|
if: >-
|
||||||
|
github.event_name == 'workflow_dispatch'
|
||||||
|
|| steps.changed.outputs.any_changed == 'true'
|
||||||
|
|
||||||
|
- name: Push image to OCI registry
|
||||||
|
run: make push-${{matrix.tag}}
|
||||||
|
if: >-
|
||||||
|
github.ref == 'refs/heads/master' &&
|
||||||
|
(github.event_name == 'workflow_dispatch' ||
|
||||||
|
(steps.changed.outputs.any_changed == 'true' && github.event_name == 'push'))
|
||||||
|
env:
|
||||||
|
REGISTRY_PASSWORD: ${{secrets.FORGEJO_OCI_REGISTRY_PUSH_TOKEN}}
|
1
CODEOWNERS
Normal file
1
CODEOWNERS
Normal file
|
@ -0,0 +1 @@
|
||||||
|
.* @TrueCloudLab/Infrastructure
|
20
Makefile
Normal file
20
Makefile
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
REGISTRY?=git.frostfs.info
|
||||||
|
REGISTRY_NAMESPACE?=truecloudlab
|
||||||
|
REGISTRY_USER?=$(REGISTRY_NAMESPACE)
|
||||||
|
REGISTRY_PASSWORD?=
|
||||||
|
|
||||||
|
IMAGE?=$(REGISTRY)/$(REGISTRY_NAMESPACE)/env
|
||||||
|
|
||||||
|
TAGS=$(patsubst %/.,%,$(wildcard */.))
|
||||||
|
.PHONY: $(TAGS)
|
||||||
|
$(TAGS):
|
||||||
|
buildah images
|
||||||
|
cd $@ && buildah bud --tag $(IMAGE):$@ .
|
||||||
|
buildah images
|
||||||
|
|
||||||
|
PUSH=$(foreach tag,$(TAGS),push-$(tag))
|
||||||
|
$(PUSH):
|
||||||
|
echo -n "$$REGISTRY_PASSWORD" | wc
|
||||||
|
echo "$$REGISTRY_PASSWORD" | buildah login --username $(REGISTRY_USER) --password-stdin $(REGISTRY)
|
||||||
|
buildah push --rm $(IMAGE):$(patsubst push-%,%,$@) docker://$(IMAGE):$(patsubst push-%,%,$@)
|
||||||
|
buildah logout $(REGISTRY)
|
22
README.md
22
README.md
|
@ -1,3 +1,21 @@
|
||||||
# WIP area: this repo is just a fork!
|
# Container environments for Forgejo Actions
|
||||||
|
|
||||||
Useful things may be published only in [other branches](../../../branches)
|
Many actions developers are targeting GitHub Actions and assume that Node.js
|
||||||
|
is available by default. This is not the case in Forgejo Actions, and we need
|
||||||
|
to add Node.js to community provided images explicitly.
|
||||||
|
|
||||||
|
This repo contains Dockerfile for images used by TrueCloudLab.
|
||||||
|
|
||||||
|
Images are published to [our registry](https://git.frostfs.info/TrueCloudLab/-/packages/container/env/versions)
|
||||||
|
|
||||||
|
## Modifying container images
|
||||||
|
|
||||||
|
Prepare a pull request with a modified or entirely new Dockerfile.
|
||||||
|
The image will get built and published after PR is merged to master.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
Images for Forgejo Actions must contain:
|
||||||
|
|
||||||
|
- Node.js
|
||||||
|
- Git
|
||||||
|
|
4
dotnet-8.0/Dockerfile
Normal file
4
dotnet-8.0/Dockerfile
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
FROM docker.io/node:20-bookworm-slim as node
|
||||||
|
FROM mcr.microsoft.com/dotnet/sdk:8.0-bookworm-slim
|
||||||
|
COPY --from=node /usr/local /usr/local
|
||||||
|
COPY --from=node /opt /opt
|
15
oci-image-builder-bookworm/Dockerfile
Normal file
15
oci-image-builder-bookworm/Dockerfile
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
FROM docker.io/node:20-bookworm-slim as node
|
||||||
|
FROM docker.io/golang:1.23-bookworm
|
||||||
|
COPY --from=node /usr/local /usr/local
|
||||||
|
COPY --from=node /opt /opt
|
||||||
|
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y buildah && \
|
||||||
|
apt-get clean && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
COPY docker-wrapper.sh /usr/local/bin/docker
|
||||||
|
|
||||||
|
# Configuration for buildah inside rootless podman
|
||||||
|
COPY containers.conf /etc/containers/containers.conf
|
||||||
|
COPY registries.conf /etc/containers/registries.conf
|
||||||
|
COPY storage.conf /etc/containers/storage.conf
|
39
oci-image-builder-bookworm/README.md
Normal file
39
oci-image-builder-bookworm/README.md
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
# Forgejo Actions environment for building OCI container images
|
||||||
|
|
||||||
|
Building OCI container images inside Forgejo Actions is somewhat non-trivial.
|
||||||
|
We need to execute Buildah inside of a rootless Podman container, which
|
||||||
|
eventually leads to a podman-in-podman scenario. Thankfully, this is not as
|
||||||
|
complex as docker-in-docker.
|
||||||
|
|
||||||
|
This image contains everything we need for executing `make image` in our
|
||||||
|
Golang repos:
|
||||||
|
|
||||||
|
- Go toolchain (for helper scripts called by Makefile)
|
||||||
|
- Docker wrapper (for abstracting Buildah away from human Makefile users)
|
||||||
|
- Podman configuration files
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Referencing this container from `.forgejo/workflows/workflow.yml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
jobs:
|
||||||
|
oci-image:
|
||||||
|
runs-on: docker
|
||||||
|
container: git.frostfs.info/truecloudlab/env:oci-image-builder-bookworm
|
||||||
|
```
|
||||||
|
|
||||||
|
See full [live
|
||||||
|
example](https://git.frostfs.info/TrueCloudLab/action-env/src/branch/master/.forgejo/workflows/build.yml)
|
||||||
|
in action in this repo.
|
||||||
|
|
||||||
|
## Initial Forgejo setup
|
||||||
|
|
||||||
|
We use this image to build all images in this repo. To avoid chicken-and-egg
|
||||||
|
situation in case of disaster recovery, the first version of this image must
|
||||||
|
be pushed from outside of Forgejo Actions, e.g. from sysadmin laptop:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ make oci-image-builder-bookworm
|
||||||
|
$ make push-oci-image-builder-bookworm
|
||||||
|
```
|
8
oci-image-builder-bookworm/containers.conf
Normal file
8
oci-image-builder-bookworm/containers.conf
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# https://github.com/containers/podman/issues/20453#issuecomment-1912725982
|
||||||
|
[containers]
|
||||||
|
cgroupns="host"
|
||||||
|
ipcns="host"
|
||||||
|
netns="host"
|
||||||
|
pidns="host"
|
||||||
|
userns="host"
|
||||||
|
utsns="host"
|
18
oci-image-builder-bookworm/docker-wrapper.sh
Executable file
18
oci-image-builder-bookworm/docker-wrapper.sh
Executable file
|
@ -0,0 +1,18 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# A wrapper that translates `docker build` commands for use with buildah
|
||||||
|
#
|
||||||
|
set -euo pipefail
|
||||||
|
while [[ $# -ne 0 ]]
|
||||||
|
do
|
||||||
|
case "$1" in
|
||||||
|
--rm|--force-rm)
|
||||||
|
# 'rm' and 'force-rm' can only be set with either 'layers' or 'no-cache'
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
args+=("$1")
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
buildah "${args[@]}"
|
11
oci-image-builder-bookworm/registries.conf
Normal file
11
oci-image-builder-bookworm/registries.conf
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
unqualified-search-registries = ["docker.io"]
|
||||||
|
|
||||||
|
[[registry]]
|
||||||
|
prefix = "docker.io"
|
||||||
|
location = "docker.io"
|
||||||
|
|
||||||
|
[[registry.mirror]]
|
||||||
|
location = "quay.io"
|
||||||
|
|
||||||
|
[[registry.mirror]]
|
||||||
|
location = "docker.io"
|
5
oci-image-builder-bookworm/storage.conf
Normal file
5
oci-image-builder-bookworm/storage.conf
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# STORAGE_DRIVER variable is ignored if /etc/containers/storage.conf does not exist
|
||||||
|
[storage]
|
||||||
|
driver = "vfs"
|
||||||
|
runroot = "/run/containers/storage"
|
||||||
|
graphroot = "/var/lib/containers/storage"
|
24
oci-runner/Dockerfile
Normal file
24
oci-runner/Dockerfile
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
FROM docker.io/node:20-bookworm-slim as node
|
||||||
|
FROM docker.io/golang:1.23-bookworm
|
||||||
|
COPY --from=node /usr/local /usr/local
|
||||||
|
COPY --from=node /opt /opt
|
||||||
|
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y podman && \
|
||||||
|
apt-get clean && \
|
||||||
|
rm -rf /var/lib/apt/lists/* && \
|
||||||
|
ln -s /usr/bin/podman /usr/local/bin/docker && \
|
||||||
|
echo root:10000:1000 > /etc/subuid && \
|
||||||
|
echo root:10000:1000 > /etc/subgid && \
|
||||||
|
echo '#!/bin/bash\npodman system service -t 0 unix:///tmp/podman-service.socket &\ndisown' > /usr/local/bin/podman-service.sh && \
|
||||||
|
chmod +x /usr/local/bin/podman-service.sh
|
||||||
|
|
||||||
|
# Configuration for podman inside rootless podman
|
||||||
|
COPY containers.conf /etc/containers/containers.conf
|
||||||
|
COPY registries.conf /etc/containers/registries.conf
|
||||||
|
COPY storage.conf /etc/containers/storage.conf
|
||||||
|
|
||||||
|
# Configuration for testcontainers
|
||||||
|
ENV DOCKER_HOST=unix:///tmp/podman-service.socket
|
||||||
|
ENV TESTCONTAINERS_DOCKER_SOCKER_OVERRIDE=/tmp/podman-service.socket
|
||||||
|
ENV TESTCONTAINERS_RYUK_DISABLED=true
|
47
oci-runner/README.md
Normal file
47
oci-runner/README.md
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
# Forgejo Actions environment for launching nested OCI containers
|
||||||
|
|
||||||
|
This image contains everything we need for executing tests
|
||||||
|
which spawn nested containers:
|
||||||
|
|
||||||
|
- Go toolchain
|
||||||
|
- Docker wrapper (for abstracting Podman away from users)
|
||||||
|
- Podman configuration files
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Referencing this container from `.forgejo/workflows/workflow.yml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
jobs:
|
||||||
|
oci-image:
|
||||||
|
runs-on: oci-runner
|
||||||
|
```
|
||||||
|
|
||||||
|
## Privileges
|
||||||
|
|
||||||
|
Managing network connectivity between nested containers requires extra
|
||||||
|
privileges on the outer container:
|
||||||
|
|
||||||
|
- CAP_NET_ADMIN (fixes `netavark: Netlink error: Operation not permitted`)
|
||||||
|
- CAP_SYS_ADMIN (fixes `slirp4netns failed: "open(/dev/net/tun): No such file or directory`)
|
||||||
|
|
||||||
|
These privileges are not required for running a single container inside
|
||||||
|
rootless Podman.
|
||||||
|
Use `--net=host --uts=host --pid=host --cgroups=enabled` to launch inner containers then.
|
||||||
|
|
||||||
|
Example of privileged outer container:
|
||||||
|
|
||||||
|
```
|
||||||
|
podman run \
|
||||||
|
--cap-add CAP_NET_ADMIN --cap-add CAP_SYS_ADMIN \
|
||||||
|
--rm -it git.frostfs.info/truecloudlab/env:oci-runner \
|
||||||
|
podman run --name hi hello-world
|
||||||
|
```
|
||||||
|
|
||||||
|
Unprivileged outer container:
|
||||||
|
|
||||||
|
```
|
||||||
|
podman run \
|
||||||
|
--rm -it git.frostfs.info/truecloudlab/env:oci-runner \
|
||||||
|
podman run --net=host --uts=host --pid=host --cgroups=enabled hello-world
|
||||||
|
```
|
21
oci-runner/containers.conf
Normal file
21
oci-runner/containers.conf
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
[containers]
|
||||||
|
|
||||||
|
# Basic podman-in-podman config from quay.io/podman/stable
|
||||||
|
cgroupns="host"
|
||||||
|
cgroups="disabled"
|
||||||
|
ipcns="host"
|
||||||
|
pidns="private"
|
||||||
|
userns="host"
|
||||||
|
|
||||||
|
# Allow network connectivity between second order containers
|
||||||
|
netns="private"
|
||||||
|
utsns="private"
|
||||||
|
|
||||||
|
# Workaround for ping_group_range error: https://github.com/containers/podman/issues/13194
|
||||||
|
default_sysctls = []
|
||||||
|
|
||||||
|
|
||||||
|
[engine]
|
||||||
|
|
||||||
|
# Basic podman-in-podman config from quay.io/podman/stable
|
||||||
|
cgroup_manager="cgroupfs"
|
11
oci-runner/registries.conf
Normal file
11
oci-runner/registries.conf
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
unqualified-search-registries = ["docker.io"]
|
||||||
|
|
||||||
|
[[registry]]
|
||||||
|
prefix = "docker.io"
|
||||||
|
location = "docker.io"
|
||||||
|
|
||||||
|
[[registry.mirror]]
|
||||||
|
location = "quay.io"
|
||||||
|
|
||||||
|
[[registry.mirror]]
|
||||||
|
location = "docker.io"
|
5
oci-runner/storage.conf
Normal file
5
oci-runner/storage.conf
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# STORAGE_DRIVER variable is ignored if /etc/containers/storage.conf does not exist
|
||||||
|
[storage]
|
||||||
|
driver = "vfs"
|
||||||
|
runroot = "/run/containers/storage"
|
||||||
|
graphroot = "/var/lib/containers/storage"
|
4
openjdk-11-maven-3.8.6/Dockerfile
Normal file
4
openjdk-11-maven-3.8.6/Dockerfile
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
FROM docker.io/node:20-bullseye-slim as node
|
||||||
|
FROM docker.io/maven:3.8.6-openjdk-11
|
||||||
|
COPY --from=node /usr/local /usr/local
|
||||||
|
COPY --from=node /opt /opt
|
4
python-3.11/Dockerfile
Normal file
4
python-3.11/Dockerfile
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
FROM docker.io/node:20-bookworm-slim as node
|
||||||
|
FROM docker.io/python:3.11-bookworm
|
||||||
|
COPY --from=node /usr/local /usr/local
|
||||||
|
COPY --from=node /opt /opt
|
4
python-3.13/Dockerfile
Normal file
4
python-3.13/Dockerfile
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
FROM docker.io/node:20-bookworm-slim as node
|
||||||
|
FROM docker.io/python:3.13-bookworm
|
||||||
|
COPY --from=node /usr/local /usr/local
|
||||||
|
COPY --from=node /opt /opt
|
Loading…
Reference in a new issue