├── noextract-python.conf ├── noextract.conf ├── setup.sh ├── COPYING ├── docker-bake.hcl ├── keys ├── 3d:b9:c0:50:41:a7:68:4c:2e:2c:a9:a2:5a:04:b7:3f.plist └── 60:ae:0c:d6:f0:95:17:80:bc:93:46:7a:89:af:a3:2d.plist ├── README.md ├── Containerfile └── .github └── workflows └── build.yaml /noextract-python.conf: -------------------------------------------------------------------------------- 1 | noextract=/usr/lib/python*/EXTERNALLY-MANAGED 2 | -------------------------------------------------------------------------------- /noextract.conf: -------------------------------------------------------------------------------- 1 | noextract=/usr/share/man* 2 | noextract=/usr/lib/dracut* 3 | noextract=/etc/hosts 4 | noextract=/etc/mtab 5 | noextract=/etc/skel* 6 | noextract=/usr/lib/modprobe.d* 7 | noextract=/usr/lib/sysctl.d* 8 | noextract=/usr/lib/udev* 9 | noextract=/usr/share/bash-completion* 10 | noextract=/usr/share/fish/vendor_completions.d* 11 | noextract=/usr/share/zsh/site-functions* 12 | noextract=/usr/share/info* 13 | noextract=/usr/lib/gconv* 14 | -------------------------------------------------------------------------------- /setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | : "${MIRROR:=https://repo-ci.voidlinux.org/}" 4 | 5 | suffix() { 6 | case "${LIBC:?}" in 7 | musl) echo "-musl" ;; 8 | esac 9 | } 10 | 11 | repo() { 12 | case "${ARCH:?}" in 13 | aarch64*) echo "${MIRROR}/current/aarch64" ;; 14 | *-musl) echo "${MIRROR}/current/musl" ;; 15 | *) echo "${MIRROR}/current" ;; 16 | esac 17 | } 18 | 19 | case "${TARGETPLATFORM:?}" in 20 | linux/arm/v6) ARCH="armv6l$(suffix)" ;; 21 | linux/arm/v7) ARCH="armv7l$(suffix)" ;; 22 | linux/arm64) ARCH="aarch64$(suffix)" ;; 23 | linux/amd64) ARCH="x86_64$(suffix)" ;; 24 | linux/386) ARCH="i686$(suffix)" ;; 25 | esac 26 | 27 | REPO="$(repo)" 28 | 29 | export ARCH REPO 30 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2008-2020 Juan Romero Pardines and contributors 2 | Copyright (c) 2017-2023 The Void Linux team and contributors 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions 7 | are met: 8 | 1. Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /docker-bake.hcl: -------------------------------------------------------------------------------- 1 | variable "MIRROR" { 2 | default = "https://repo-ci.voidlinux.org/" 3 | } 4 | 5 | target "docker-metadata-action" {} 6 | 7 | target "_common" { 8 | inherits = ["docker-metadata-action"] 9 | dockerfile = "Containerfile" 10 | no-cache-filter = ["bootstrap"] 11 | cache-to = ["type=local,dest=/tmp/buildx-cache"] 12 | cache-from = ["type=local,src=/tmp/buildx-cache"] 13 | args = { 14 | "MIRROR" = "${MIRROR}" 15 | } 16 | } 17 | 18 | target "_common-glibc" { 19 | inherits = ["_common"] 20 | platforms = ["linux/amd64", "linux/386", "linux/arm64", "linux/arm/v7", "linux/arm/v6"] 21 | args = { "LIBC" = "glibc" } 22 | } 23 | 24 | target "_common-musl" { 25 | inherits = ["_common"] 26 | platforms = ["linux/amd64", "linux/arm64", "linux/arm/v7", "linux/arm/v6"] 27 | args = { "LIBC" = "musl" } 28 | } 29 | 30 | target "void-glibc" { 31 | inherits = ["_common-glibc"] 32 | target = "image-default" 33 | } 34 | 35 | target "void-glibc-busybox" { 36 | inherits = ["_common-glibc"] 37 | target = "image-busybox" 38 | } 39 | 40 | target "void-glibc-full" { 41 | inherits = ["_common-glibc"] 42 | target = "image-full" 43 | } 44 | 45 | target "void-musl" { 46 | inherits = ["_common-musl"] 47 | target = "image-default" 48 | } 49 | 50 | target "void-musl-busybox" { 51 | inherits = ["_common-musl"] 52 | target = "image-busybox" 53 | } 54 | 55 | target "void-musl-full" { 56 | inherits = ["_common-musl"] 57 | target = "image-full" 58 | } 59 | -------------------------------------------------------------------------------- /keys/3d:b9:c0:50:41:a7:68:4c:2e:2c:a9:a2:5a:04:b7:3f.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | public-key 6 | LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUFvM1Nrc2p5N01PMmc4UWxsZjdCVQp1aXhFUWlqN3FOSVJrU0hrWWw4SGxxd1hOczFnK1FzbzhGV3dSbDNMbUpTVW5wT1BaOG1sdVdSajd4Y2pLbnVJCnhPRjBtQS8vM0lzTnVId2dYV2RLL0JiT29wNzFLZmt4aEE0WjhwK0hRbmhLMThxUkFPbG9xOGJ6WXZhaGI2NmEKemdWVTVFM1JzRDU4V0M2ZTFOUVdSSGpiMG1TM2h6M1NxVWVWZFVMT20zVzZBRTdYdWlVQVJOSEdyY1ljMXkyKwpxNjBKWHMrVk5sRlMwaGdDdnpqS3phMVg5cWtzQndzTmdaRlhBcXN1MGFKRndYSTEvM2R4ZWxBcUZFbnRMWVFSCjA4NHpaTDFmWDVRMWlacGNEaHVhTWZVREVZQjA4UzdKTTBYKytibkxxVnphVTZzc0RXdGtzbFJaNjNaVStISTUKemk5a0pyc25LcU5Pa3BKSnJTUkRyMGFvRjV2RDRwN20vYWdZKzdTRk5aaDZzOUJ5V0x3NDVFdytwalVVUmp5aQp6T01TSFhEM3YzczhFdzZkV29wbTVQTGUvUEgzZWFiMEVnbG9yVDZhYmRwaCtaVG4zaUxMWVVkSGNmQ1FDN01GCkNmVGl1TWt4SkJpaCtoOEhKaUlBdmpDZjVxdjZiaFpEUHpGRzAwbEpYRUZwNHRpbGp6eTFmbitiMkdLY3BDOWQKUUs4TEc3M0RFaXhacHBmU09IU09MMWYxVlBzZTBRdnl6d2RWc0xzR0dqV0FaZkw4WUdVZDl4Y20yeW5tVzFuNgpKTjl6NE9oZ3lRa21mNUFFUXpYSUxQR0d1MlREUVh5c05IRG0vUnRMMHJPN3cxbFVKSTVYOW1kbEZYd0xUWHI3ClYrU25aK3U5VCtFREg1NTV6WDJDZTgwQ0F3RUFBUT09Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQo= 7 | public-key-size 8 | 4096 9 | signature-by 10 | Void Linux 11 | 12 | 13 | -------------------------------------------------------------------------------- /keys/60:ae:0c:d6:f0:95:17:80:bc:93:46:7a:89:af:a3:2d.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | public-key 6 | LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUF2clN6QlpNdmd2T0NJM0FYYk9qYQoycktSa0pTVE0zYy9FalRJZ0NnRFhndW05M0JQQ3RZOE1jRlZvQ1U0T2lYSEdmVG1xMzlCVk5wTHZMSEw5S2sxCnAyNzhTQmhYVk90YkIyRVZtREtudmZJREVUbGRMR3plN3JaTlJKZHR1TjJtWi9UVnJVQjlTMHlRYytJdWY0aHYKMytEOTdWSWRUSkhBN0FTcjA0MjhwcEVHSkd3U1NoWTJYSm05RDVJMEV1R1JXYzE0TUVHN2RJS0ppWWlNMG5FNAp0WW8yL3ZINElGVEhkblZBM2dZaVp5RG5idUNBUi84RVNmVVRVMTNTTkNPZGJ1ZGYzRDVCY3krVWlNREpJM1llCjRNRktCclQ5WmhaK0dzWEJaWTQ4MmxxaVppNkNMNXB0YzlJUUZmOC9lS1phOGphdGtpVkZWZ3JLZU5Sak9UeE4KZldTdTJua3hHTlgrYmhYWXRoaUdXbUpFWThjQ0FQeUZOK0x2NVJldEsyNTZnZGNiMnNrbUVxZWZ2MnpQQyt3VgpXQmJkSDViRDRiWmpuME42Wmw4MXJ2NVJ6RHZudmYrdkQxNGFGVWJaOFFGcXU3NVBiTDR3Nm1ZTTRsZE0vZzBSCjZOWEU4QXo5Qnd4MnREZlllS3V1dHcxRXBQbTJZdkZ5VFViMWNveUF1VEdSeUFhcDFVVEh2ZzlsaFBJSm1oRlEKSjVrQ2cxcUQ3QTMxV2wwUmxuZTZoZ0dvMFpaTko1Y0pNL3YvelNUS0pjdUZnd283SDBoT0dpbDZEZm84OUI0agpHOTZBQ3lQUytEVktQRlhSWXdqL0FrYkhwYVEyZjFGTUFvU3BCcXVEcUhoM3VrazcxS1g2ajE5dDBpRjhEUUxyCnZ0RlNTZElqREEwMmx3ZVY5TmFRcFdzQ0F3RUFBUT09Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQo= 7 | public-key-size 8 | 4096 9 | signature-by 10 | Void Linux 11 | 12 | 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Void Linux Container Images 2 | 3 | This repo contains what is needed to build void-linux OCI container 4 | images. There are 3 images provided for each libc (`glibc` or `musl`): 5 | 6 | - `void-LIBC`: This image contains far fewer packages and uses a 7 | `noextract` file to prevent certain directories from being added to 8 | the image. These images average 40-65MB. 9 | 10 | - `void-LIBC-full`: Large image based on the `base-container` package and 11 | does not contain a `noextract` configuration. If you want something 12 | that is as close to a full void VM as possible, this is the image you 13 | want to start with.These images average 80-135MB. 14 | 15 | - `void-LIBC-busybox`: This image is the same as the `void-LIBC` image 16 | above, but uses busybox instead of GNU coreutils. Note that this is 17 | not a well tested configuration with Void, but if you want a very 18 | small image, busybox is a good way to get it. These images average 15-40MB. 19 | 20 | These images are available for the following OCI platforms: 21 | 22 | - `linux/amd64` 23 | - `linux/386` (`glibc` only) 24 | - `linux/arm64` 25 | - `linux/arm/v7` 26 | - `linux/arm/v6` 27 | 28 | ``` 29 | REPOSITORY TAG SIZE 30 | ghcr.io/void-linux/void-glibc latest 64.5MB 31 | ghcr.io/void-linux/void-musl latest 40.3MB 32 | ghcr.io/void-linux/void-glibc-full latest 135MB 33 | ghcr.io/void-linux/void-musl-full latest 81.4MB 34 | ghcr.io/void-linux/void-glibc-busybox latest 39.6MB 35 | ghcr.io/void-linux/void-musl-busybox latest 14.4MB 36 | ``` 37 | 38 | ## Building locally 39 | 40 | With `docker` and `docker-buildx`: 41 | 42 | 1. Install and set up `docker` and `docker-buildx`. If building multi-platform images, 43 | `qemu-user-static`, and `binfmt-support` are also needed: 44 | ```sh 45 | xbps-install docker docker-buildx 46 | ln -s /etc/sv/docker /var/service 47 | # optional 48 | xbps-install binfmt-support 49 | ln -s /etc/sv/binfmt-support /var/service 50 | xbps-install qemu-user-static 51 | ``` 52 | 2. Build the image: 53 | ```sh 54 | docker build --target "image-" -f Containerfile --build-arg="LIBC=" . --tag 55 | ``` 56 | > Note: To easily build multi-platform images, `docker buildx bake` can be used. 57 | 58 | With `podman`: 59 | 60 | 1. Install and set up `podman`. 61 | 2. Build the image: 62 | ```sh 63 | podman build --target "image-" --build-arg="LIBC=" . --tag 64 | ``` 65 | -------------------------------------------------------------------------------- /Containerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1 2 | FROM --platform=${BUILDPLATFORM} alpine:3.22 AS bootstrap 3 | ARG TARGETPLATFORM 4 | ARG MIRROR=https://repo-ci.voidlinux.org 5 | ARG LIBC 6 | RUN apk add ca-certificates curl && \ 7 | curl "${MIRROR}/static/xbps-static-static-0.59_5.$(uname -m)-musl.tar.xz" | tar vJx 8 | COPY keys/* /target/var/db/xbps/keys/ 9 | COPY setup.sh /bootstrap/setup.sh 10 | COPY noextract-python.conf /target/etc/xbps.d/noextract-python.conf 11 | RUN --mount=type=cache,sharing=locked,target=/target/var/cache/xbps,id=repocache-${LIBC} \ 12 | . /bootstrap/setup.sh; \ 13 | XBPS_TARGET_ARCH=${ARCH} xbps-install -S \ 14 | -R "${REPO}" \ 15 | -r /target 16 | 17 | FROM --platform=${BUILDPLATFORM} bootstrap AS install-default 18 | ARG TARGETPLATFORM 19 | ARG MIRROR 20 | ARG LIBC 21 | COPY --from=bootstrap /target /target 22 | COPY noextract.conf /target/etc/xbps.d/noextract.conf 23 | RUN --mount=type=cache,sharing=locked,target=/target/var/cache/xbps,id=repocache-${LIBC} \ 24 | . /bootstrap/setup.sh; \ 25 | XBPS_TARGET_ARCH=${ARCH} xbps-install -y \ 26 | -R "${REPO}" \ 27 | -r /target \ 28 | xbps base-files dash coreutils grep run-parts sed gawk 29 | 30 | FROM --platform=${BUILDPLATFORM} bootstrap AS install-busybox 31 | ARG TARGETPLATFORM 32 | ARG MIRROR 33 | ARG LIBC 34 | COPY --from=bootstrap /target /target 35 | COPY noextract.conf /target/etc/xbps.d/noextract.conf 36 | RUN --mount=type=cache,sharing=locked,target=/target/var/cache/xbps,id=repocache-${LIBC} \ 37 | . /bootstrap/setup.sh; \ 38 | XBPS_TARGET_ARCH=${ARCH} xbps-install -y \ 39 | -R "${REPO}" \ 40 | -r /target \ 41 | xbps base-files busybox-huge 42 | 43 | FROM --platform=${BUILDPLATFORM} bootstrap AS install-full 44 | ARG TARGETPLATFORM 45 | ARG MIRROR 46 | ARG LIBC 47 | COPY --from=bootstrap /target /target 48 | RUN --mount=type=cache,sharing=locked,target=/target/var/cache/xbps,id=repocache-${LIBC} \ 49 | . /bootstrap/setup.sh; \ 50 | XBPS_TARGET_ARCH=${ARCH} xbps-install -y \ 51 | -R "${REPO}" \ 52 | -r /target \ 53 | base-container 54 | 55 | FROM scratch AS image-default 56 | COPY --link --from=install-default /target / 57 | RUN \ 58 | install -dm1777 tmp; \ 59 | xbps-reconfigure -fa; \ 60 | rm -rf /var/cache/xbps/* 61 | CMD ["/bin/sh"] 62 | 63 | FROM scratch AS image-busybox 64 | COPY --link --from=install-busybox /target / 65 | RUN \ 66 | for util in $(/usr/bin/busybox --list); do \ 67 | [ ! -f "/usr/bin/$util" ] && /usr/bin/busybox ln -sfv busybox "/usr/bin/$util"; \ 68 | done; \ 69 | install -dm1777 tmp; \ 70 | xbps-reconfigure -fa; \ 71 | rm -rf /var/cache/xbps/* 72 | CMD ["/bin/sh"] 73 | 74 | FROM scratch AS image-full 75 | COPY --link --from=install-full /target / 76 | RUN \ 77 | install -dm1777 tmp; \ 78 | xbps-reconfigure -fa; \ 79 | rm -rf /var/cache/xbps/* 80 | CMD ["/bin/sh"] 81 | -------------------------------------------------------------------------------- /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: 'Build containers' 3 | 4 | on: 5 | schedule: 6 | - cron: "0 0 1 * *" 7 | workflow_dispatch: 8 | pull_request: 9 | branches: 10 | - master 11 | paths-ignore: 12 | - COPYING 13 | - README.md 14 | push: 15 | branches: 16 | - master 17 | paths-ignore: 18 | - COPYING 19 | - README.md 20 | 21 | concurrency: 22 | group: ${{ github.workflow }}-${{ github.ref }} 23 | cancel-in-progress: true 24 | 25 | jobs: 26 | build: 27 | runs-on: ubuntu-latest 28 | 29 | strategy: 30 | matrix: 31 | libc: 32 | - 'glibc' 33 | - 'musl' 34 | variant: 35 | - '' 36 | - '-full' 37 | - '-busybox' 38 | 39 | steps: 40 | - name: Checkout 41 | uses: classabbyamp/treeless-checkout-action@v1 42 | 43 | - name: Get image release 44 | id: release 45 | run: | 46 | # gets the list of all date-shaped tags for the image, finds the most recent one 47 | tag="$(skopeo list-tags "docker://ghcr.io/${{ github.repository_owner }}/void-${{ matrix.libc }}${{ matrix.variant }}" | \ 48 | jq -r '.Tags | sort | reverse | map(select(test("^[0-9]{8}(R[0-9]+)?$")))[0]')" 49 | # tags from a different day or pre-YYYYMMDDRN 50 | if [ "${tag%R*}" != "$(date -u +%Y%m%d)" ] || [ "${tag%R*}" = "${tag}" ]; then 51 | rel=1 52 | else 53 | rel=$(( ${tag##*R} + 1 )) 54 | fi 55 | echo "rel=${rel}" >> "${GITHUB_OUTPUT}" 56 | 57 | - name: Docker metadata 58 | id: meta 59 | uses: docker/metadata-action@v4 60 | with: 61 | images: | 62 | ghcr.io/${{ github.repository_owner }}/void-${{ matrix.libc }}${{ matrix.variant }} 63 | tags: | 64 | type=sha,prefix= 65 | type=raw,value=latest,enable={{is_default_branch}} 66 | type=raw,value={{date 'YYYYMMDD'}}R${{ steps.release.outputs.rel }},enable={{is_default_branch}},priority=1000 67 | flavor: latest=false 68 | labels: | 69 | org.opencontainers.image.authors=Void Linux team and contributors 70 | org.opencontainers.image.url=https://voidlinux.org 71 | org.opencontainers.image.documentation=https://docs.voidlinux.org 72 | org.opencontainers.image.source=https://github.com/${{ github.repository }} 73 | org.opencontainers.image.vendor=Void Linux 74 | org.opencontainers.image.title=Void Linux 75 | org.opencontainers.image.description=general-purpose image based on Void Linux 76 | annotations: | 77 | org.opencontainers.image.authors=Void Linux team and contributors 78 | org.opencontainers.image.url=https://voidlinux.org 79 | org.opencontainers.image.documentation=https://docs.voidlinux.org 80 | org.opencontainers.image.source=https://github.com/${{ github.repository }} 81 | org.opencontainers.image.vendor=Void Linux 82 | org.opencontainers.image.title=Void Linux 83 | org.opencontainers.image.description=general-purpose image based on Void Linux 84 | 85 | - name: Set up QEMU 86 | uses: docker/setup-qemu-action@v2 87 | 88 | - name: Set up Docker Buildx 89 | uses: docker/setup-buildx-action@v2 90 | 91 | - name: Login to GHCR 92 | if: github.event_name != 'pull_request' 93 | uses: docker/login-action@v2 94 | with: 95 | registry: ghcr.io 96 | username: ${{ github.actor }} 97 | password: ${{ secrets.GITHUB_TOKEN }} 98 | 99 | - name: Build and push images 100 | id: build_and_push 101 | uses: docker/bake-action@v5 102 | with: 103 | push: ${{ github.event_name != 'pull_request' }} 104 | targets: void-${{ matrix.libc }}${{ matrix.variant }} 105 | files: | 106 | docker-bake.hcl 107 | ${{ steps.meta.outputs.bake-file }} 108 | set: | 109 | _common.cache-to=type=gha 110 | _common.cache-from=type=gha 111 | provenance: false 112 | sbom: false 113 | --------------------------------------------------------------------------------