├── .travis.yml ├── Dockerfile.arm32v7 ├── Dockerfile.arm64v8 ├── LICENSE ├── README.md ├── build ├── create-manifest ├── pacstrap-docker ├── prepare-qemu ├── push └── rootfs ├── etc ├── locale.conf ├── locale.gen └── pacman.d │ └── mirrorlist └── usr └── share └── libalpm └── hooks ├── man-page-remove.hook └── package-cleanup.hook /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: xenial 2 | language: generic 3 | sudo: required 4 | go: 5 | - stable 6 | services: 7 | - docker 8 | env: 9 | - BUILD_ARCH=arm32v7 10 | - BUILD_ARCH=arm64v8 11 | install: 12 | - 'echo ''{ "experimental": true }'' | sudo tee /etc/docker/daemon.json' 13 | - sudo systemctl restart docker 14 | - sudo apt-get --yes --no-install-recommends install qemu-user-static 15 | before_script: 16 | - sudo ./prepare-qemu 17 | - chmod -R g-w ./ 18 | script: 19 | - ./build 20 | after_success: 21 | - '[ "$TRAVIS_PULL_REQUEST" == "false" ] && docker login -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD" && ./push' 22 | 23 | jobs: 24 | include: 25 | - stage: deploy 26 | name: "Create Manifest" 27 | install: 'mkdir $HOME/.docker/ && echo ''{ "experimental": "enabled" }'' > $HOME/.docker/config.json' 28 | before_script: docker login -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD" 29 | script: ./create-manifest 30 | -------------------------------------------------------------------------------- /Dockerfile.arm32v7: -------------------------------------------------------------------------------- 1 | FROM agners/archlinuxarm-arm32v7 2 | 3 | WORKDIR /archlinux 4 | 5 | RUN mkdir -p /archlinux/rootfs 6 | 7 | COPY pacstrap-docker /archlinux/ 8 | 9 | RUN ./pacstrap-docker /archlinux/rootfs \ 10 | bash sed gzip pacman 11 | 12 | # Remove current pacman database, likely outdated very soon 13 | RUN rm rootfs/var/lib/pacman/sync/* 14 | RUN ls -la /archlinux/rootfs/ 15 | 16 | FROM scratch 17 | COPY --from=0 /archlinux/rootfs/ / 18 | RUN ls -la / 19 | COPY rootfs/ / 20 | 21 | ENV LANG=en_US.UTF-8 22 | 23 | RUN ls -la / 24 | RUN locale-gen 25 | RUN pacman-key --init 26 | RUN pacman-key --populate archlinuxarm 27 | 28 | CMD ["/usr/bin/bash"] 29 | -------------------------------------------------------------------------------- /Dockerfile.arm64v8: -------------------------------------------------------------------------------- 1 | FROM agners/archlinuxarm-arm64v8 2 | 3 | WORKDIR /archlinux 4 | 5 | RUN mkdir -p /archlinux/rootfs 6 | 7 | COPY pacstrap-docker /archlinux/ 8 | 9 | RUN ./pacstrap-docker /archlinux/rootfs \ 10 | bash sed gzip pacman 11 | 12 | # Remove current pacman database, likely outdated very soon 13 | RUN rm rootfs/var/lib/pacman/sync/* 14 | 15 | FROM scratch 16 | COPY --from=0 /archlinux/rootfs/ / 17 | COPY rootfs/ / 18 | 19 | ENV LANG=en_US.UTF-8 20 | 21 | RUN locale-gen 22 | RUN pacman-key --init 23 | RUN pacman-key --populate archlinuxarm 24 | 25 | CMD ["/usr/bin/bash"] 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Stefan Agner 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Basic Arch Linux ARM Docker images [![Build Status](https://travis-ci.org/agners/archlinuxarm-docker.svg?branch=master)](https://travis-ci.org/agners/archlinuxarm-docker) 2 | 3 | Docker images for Arch Linux ARM on AArch32 (ARMv7-A) and AArch64 (ARMv8-A). Built using native pacman and Docker multi-stage builds. Builds weekly by Travis CI on publicly visible infrastructure using Qemu emulation. 4 | 5 | ## Running the images 6 | 7 | The images are on [Docker Hub](https://hub.docker.com/u/agners/). Use the convenient `docker run`: 8 | 9 | docker run --rm -ti agners/archlinuxarm 10 | 11 | Instead of using the multi-arch container above, you can also get the architecture specific image directly: 12 | 13 | docker run --rm -ti agners/archlinuxarm-arm32v7 14 | 15 | ## Tags 16 | 17 | | Tag | Update | Type | Description | 18 | |:------:|:----------:|:-------:|:-----------------------------------------------------------------------------------| 19 | | latest | **weekly** | minimal | minimal Arch Linux ARM with pacman support | 20 | 21 | ### Layer structure 22 | 23 | The image is generated from a freshly built pacman rootfs. Pacman has configured 24 | to delete man pages and clean the package cache after installation to keep 25 | images small. 26 | 27 | ## Issues and improvements 28 | 29 | If you want to contribute, get to the [issues-section of this repository](https://github.com/agners/archlinuxarm-docker/issues). 30 | 31 | ## Common hurdles 32 | 33 | ### Setting the timezone 34 | 35 | Simply add the `TZ` environment-variable and define it with a valid timezone-value. 36 | 37 | ``` 38 | docker run -e TZ=Europe/Berlin agners/archlinuxarm 39 | ``` 40 | 41 | ## Building it yourself 42 | 43 | ### Prerequisites 44 | 45 | - Docker with experimental mode on (required for squash) 46 | - sudo or root is neccessary to setup binfmt for Qemu user mode emulation 47 | 48 | ### Building 49 | 50 | - Prepare binfmt use with Qemu user mode using `sudo ./prepare-qemu` 51 | - Run `BUILD_ARCH= ./build` to build 52 | - Use `BUILD_ARCH=arm32v7` for ARMv7 Aarch32 53 | - Use `BUILD_ARCH=arm64v8` for ARMv8 Aarch64 54 | 55 | If you want to push the images, run `./push`. *But be aware you have no push access to the repos! Edit the scripts to push to custom Docker Hub locations!* 56 | 57 | ### Building from scratch 58 | 59 | Since the image depends on itself, the question which arise is how this all 60 | started. The initial containers have been created using the tarballs provided by 61 | the Arch Linux ARM project. I used the following steps to bootstrap for each 62 | architecture: 63 | 64 | ``` 65 | sudo tar xvzf ArchLinuxARM-armv7-latest.tar.gz -C tmp-arch 66 | sudo tar cf ArchLinuxARM-armv7-latest.tar -C tmp-arch/ . 67 | docker import ArchLinuxARM-armv7-latest.tar agners/armv7-archlinux:latest 68 | ``` 69 | 70 | ## Credits 71 | 72 | Ideas have been taken from already existing Docker files for Arch Linux. 73 | However, this repository takes a slightly different approach to create images. 74 | 75 | - https://github.com/archlinux/archlinux-docker 76 | - Focus on Arch Linux for x86 77 | - Uses docker run in priviledged mode to build images 78 | - https://github.com/lopsided98/archlinux 79 | - Uses prebuilt tarballs which contain packages not required in containers 80 | -------------------------------------------------------------------------------- /build: -------------------------------------------------------------------------------- 1 | #!/bin/bash -ex 2 | 3 | DOCKER_ARCH=${BUILD_ARCH:-arm32v7} 4 | DOCKER_ORG=agners 5 | DOCKER_IMAGE=archlinuxarm-${DOCKER_ARCH} 6 | 7 | TAG_DATE=$(date +'%Y%m%d') 8 | 9 | docker build -t $DOCKER_ORG/$DOCKER_IMAGE \ 10 | -t $DOCKER_ORG/$DOCKER_IMAGE:$TAG_DATE \ 11 | -f Dockerfile.${DOCKER_ARCH} . 12 | 13 | -------------------------------------------------------------------------------- /create-manifest: -------------------------------------------------------------------------------- 1 | #!/bin/bash -ex 2 | 3 | DOCKER_ORG=agners 4 | DOCKER_IMAGE=archlinuxarm 5 | 6 | TAGS="latest $(date +'%Y%m%d')" 7 | 8 | for TAG in $TAGS 9 | do 10 | docker manifest create --amend $DOCKER_ORG/$DOCKER_IMAGE:$TAG \ 11 | $DOCKER_ORG/$DOCKER_IMAGE-arm32v7:$TAG \ 12 | $DOCKER_ORG/$DOCKER_IMAGE-arm64v8:$TAG 13 | 14 | docker manifest annotate $DOCKER_ORG/$DOCKER_IMAGE:$TAG \ 15 | $DOCKER_ORG/$DOCKER_IMAGE-arm32v7:$TAG \ 16 | --os linux --arch arm --variant v7 17 | 18 | docker manifest annotate $DOCKER_ORG/$DOCKER_IMAGE:$TAG \ 19 | $DOCKER_ORG/$DOCKER_IMAGE-arm64v8:$TAG \ 20 | --os linux --arch arm64 --variant v8 21 | 22 | docker manifest push $DOCKER_ORG/$DOCKER_IMAGE:$TAG 23 | done 24 | -------------------------------------------------------------------------------- /pacstrap-docker: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | out() { printf "$1 $2\n" "${@:3}"; } 4 | error() { out "==> ERROR:" "$@"; } >&2 5 | die() { error "$@"; exit 1; } 6 | 7 | (( $# )) || die "No root directory specified" 8 | newroot=$1; shift 9 | pacman_args=("${@:-base}") 10 | 11 | if [[ $EUID -ne 0 ]]; then 12 | die "This script must be run as root" 13 | fi 14 | 15 | [[ -d $newroot ]] || die "%s is not a directory" "$newroot" 16 | 17 | echo 'Creating install root at %s' "$newroot" 18 | mkdir -m 0755 -p "$newroot"/var/{cache/pacman/pkg,lib/pacman,log} "$newroot"/{dev,run,etc} 19 | mkdir -m 1777 -p "$newroot"/tmp 20 | mkdir -m 0555 -p "$newroot"/{sys,proc} 21 | 22 | echo 'Creating /dev/null in new root' 23 | mknod "$newroot/dev/null" c 1 3 24 | 25 | echo 'Installing packages to %s' "$newroot" 26 | if ! pacman -r "$newroot" -Sy --noconfirm "${pacman_args[@]}"; then 27 | die 'Failed to install packages to new root' 28 | fi 29 | 30 | echo 'Deleting /dev/null from new root' 31 | rm "$newroot/dev/null" 32 | -------------------------------------------------------------------------------- /prepare-qemu: -------------------------------------------------------------------------------- 1 | #!/bin/bash -ex 2 | 3 | if [[ $EUID -ne 0 ]]; then 4 | echo "This script must be run as root" 5 | exit 1 6 | fi 7 | 8 | # Delete currently existing configurations 9 | if [ -f /proc/sys/fs/binfmt_misc/qemu-arm ]; then 10 | echo -1 > /proc/sys/fs/binfmt_misc/qemu-arm 11 | fi 12 | if [ -f /proc/sys/fs/binfmt_misc/qemu-aarch64 ]; then 13 | echo -1 > /proc/sys/fs/binfmt_misc/qemu-aarch64 14 | fi 15 | 16 | echo ':qemu-arm:M:0:\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-arm-static:CF' > /proc/sys/fs/binfmt_misc/register 17 | 18 | echo ':qemu-aarch64:M:0:\x7f\x45\x4c\x46\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-aarch64-static:CF' > /proc/sys/fs/binfmt_misc/register 19 | -------------------------------------------------------------------------------- /push: -------------------------------------------------------------------------------- 1 | #!/bin/bash -ex 2 | 3 | DOCKER_ARCH=${BUILD_ARCH:-arm32v7} 4 | DOCKER_ORG=agners 5 | DOCKER_IMAGE=archlinuxarm-${DOCKER_ARCH} 6 | 7 | TAG_DATE=$(date +'%Y%m%d') 8 | 9 | docker push $DOCKER_ORG/$DOCKER_IMAGE:$TAG_DATE 10 | docker push $DOCKER_ORG/$DOCKER_IMAGE 11 | 12 | 13 | -------------------------------------------------------------------------------- /rootfs/etc/locale.conf: -------------------------------------------------------------------------------- 1 | LANG=en_US.UTF-8 2 | -------------------------------------------------------------------------------- /rootfs/etc/locale.gen: -------------------------------------------------------------------------------- 1 | en_US.UTF-8 UTF-8 2 | -------------------------------------------------------------------------------- /rootfs/etc/pacman.d/mirrorlist: -------------------------------------------------------------------------------- 1 | # Server list generated by rankmirrors on 2020-04-17 2 | Server = http://mirror.archlinuxarm.org/$arch/$repo 3 | Server = http://pt.mirror.archlinuxarm.org/$arch/$repo 4 | Server = https://za.mirror.archlinuxarm.org/$arch/$repo 5 | Server = http://au.mirror.archlinuxarm.org/$arch/$repo 6 | Server = http://br2.mirror.archlinuxarm.org/$arch/$repo 7 | Server = http://ca.us.mirror.archlinuxarm.org/$arch/$repo 8 | Server = http://de.mirror.archlinuxarm.org/$arch/$repo 9 | Server = http://de3.mirror.archlinuxarm.org/$arch/$repo 10 | Server = http://de4.mirror.archlinuxarm.org/$arch/$repo 11 | Server = http://de5.mirror.archlinuxarm.org/$arch/$repo 12 | Server = http://dk.mirror.archlinuxarm.org/$arch/$repo 13 | Server = http://eu.mirror.archlinuxarm.org/$arch/$repo 14 | Server = http://fl.us.mirror.archlinuxarm.org/$arch/$repo 15 | Server = http://gr.mirror.archlinuxarm.org/$arch/$repo 16 | Server = http://hu.mirror.archlinuxarm.org/$arch/$repo 17 | Server = http://il.us.mirror.archlinuxarm.org/$arch/$repo 18 | Server = http://nj.us.mirror.archlinuxarm.org/$arch/$repo 19 | Server = http://nl.mirror.archlinuxarm.org/$arch/$repo 20 | Server = http://sg.mirror.archlinuxarm.org/$arch/$repo 21 | Server = http://tw.mirror.archlinuxarm.org/$arch/$repo 22 | Server = http://vn.mirror.archlinuxarm.org/$arch/$repo 23 | -------------------------------------------------------------------------------- /rootfs/usr/share/libalpm/hooks/man-page-remove.hook: -------------------------------------------------------------------------------- 1 | [Trigger] 2 | Operation = Install 3 | Operation = Upgrade 4 | Type = Package 5 | Target = * 6 | 7 | [Action] 8 | Description = Cleaning up package cache... 9 | Depends = coreutils 10 | When = PostTransaction 11 | Exec = /usr/bin/rm -rf /usr/share/man/ 12 | -------------------------------------------------------------------------------- /rootfs/usr/share/libalpm/hooks/package-cleanup.hook: -------------------------------------------------------------------------------- 1 | [Trigger] 2 | Operation = Install 3 | Operation = Upgrade 4 | Type = Package 5 | Target = * 6 | 7 | [Action] 8 | Description = Cleaning up package cache... 9 | Depends = coreutils 10 | When = PostTransaction 11 | Exec = /usr/bin/rm -rf /var/cache/pacman/pkg 12 | --------------------------------------------------------------------------------