Skip to content

Commit

Permalink
add support for ARM (#485)
Browse files Browse the repository at this point in the history
* build and run on arm64

* multiarch docker build

* add ARM64 warning to README.md
  • Loading branch information
mcrossen committed Mar 3, 2024
1 parent bd76f1c commit 98d3e47
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 28 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: build
env:
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
run: |
./build.py
./build.py --multiarch
4 changes: 3 additions & 1 deletion .github/workflows/docker_push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: build and push
if: ${{ env.DOCKER_USERNAME != '' && env.DOCKER_PASSWORD != '' }}
env:
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
run: |
./build.py --push-tags
./build.py --push-tags --multiarch
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Factorio [![Docker Version](https://img.shields.io/docker/v/factoriotools/factorio?sort=semver)](https://hub.docker.com/r/factoriotools/factorio/) [![Docker Pulls](https://img.shields.io/docker/pulls/factoriotools/factorio.svg?maxAge=600)](https://hub.docker.com/r/factoriotools/factorio/) [![Docker Stars](https://img.shields.io/docker/stars/factoriotools/factorio.svg?maxAge=600)](https://hub.docker.com/r/factoriotools/factorio/)

> [!NOTE]
> Support for ARM is experimental. Expect crashes and lag if you try to run this on a raspberry pi.
[中文](./README_zh_CN.md)

<!-- start autogeneration tags -->
Expand Down
87 changes: 67 additions & 20 deletions build.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,71 @@
import sys
import tempfile

def build_dockerfile(sha256, version, tags):
build_dir = tempfile.mktemp()
shutil.copytree("docker", build_dir)

build_command = ["docker", "build", "--build-arg", f"VERSION={version}",
"--build-arg", f"SHA256={sha256}", "."]
for tag in tags:
build_command.extend(["-t", f"factoriotools/factorio:{tag}"])
PLATFORMS = [
"linux/arm64",
"linux/amd64",
]


def create_builder(build_dir, builder_name, platform):
check_exists_command = ["docker", "buildx", "inspect", builder_name]
if subprocess.run(check_exists_command, stderr=subprocess.DEVNULL).returncode != 0:
create_command = ["docker", "buildx", "create", "--platform", platform, "--name", builder_name]
try:
subprocess.run(create_command, cwd=build_dir, check=True)
except subprocess.CalledProcessError:
print("Creating builder failed")
exit(1)


def build_and_push_multiarch(build_dir, build_args, push):
builder_name = "factoriotools-multiarch"
platform=",".join(PLATFORMS)
create_builder(build_dir, builder_name, platform)
build_command = ["docker", "buildx", "build", "--platform", platform, "--builder", builder_name] + build_args
if push:
build_command.append("--push")
try:
subprocess.run(build_command, cwd=build_dir, check=True)
except subprocess.CalledProcessError:
print("Build and push of image failed")
exit(1)


def build_singlearch(build_dir, build_args):
build_command = ["docker", "build"] + build_args
try:
subprocess.run(build_command, cwd=build_dir, check=True)
except subprocess.CalledProcessError:
print("Build of image failed")
exit(1)


def push_singlearch(tags):
for tag in tags:
try:
subprocess.run(["docker", "push", f"factoriotools/factorio:{tag}"],
check=True)
except subprocess.CalledProcessError:
print("Docker push failed")
exit(1)


def build_and_push(sha256, version, tags, push, multiarch):
build_dir = tempfile.mktemp()
shutil.copytree("docker", build_dir)
build_args = ["--build-arg", f"VERSION={version}", "--build-arg", f"SHA256={sha256}", "."]
for tag in tags:
build_args.extend(["-t", f"factoriotools/factorio:{tag}"])
if multiarch:
build_and_push_multiarch(build_dir, build_args, push)
else:
build_singlearch(build_dir, build_args)
if push:
push_singlearch(tags)


def login():
try:
username = os.environ["DOCKER_USERNAME"]
Expand All @@ -35,7 +85,7 @@ def login():
exit(1)


def main(push_tags=False):
def main(push_tags=False, multiarch=False):
with open(os.path.join(os.path.dirname(__file__), "buildinfo.json")) as file_handle:
builddata = json.load(file_handle)

Expand All @@ -45,18 +95,15 @@ def main(push_tags=False):
for version, buildinfo in builddata.items():
sha256 = buildinfo["sha256"]
tags = buildinfo["tags"]
build_dockerfile(sha256, version, tags)
if not push_tags:
continue
for tag in tags:
try:
subprocess.run(["docker", "push", f"factoriotools/factorio:{tag}"],
check=True)
except subprocess.CalledProcessError:
print("Docker push failed")
exit(1)
build_and_push(sha256, version, tags, push_tags, multiarch)


if __name__ == '__main__':
push_tags = len(sys.argv) > 1 and sys.argv[1] == "--push-tags"
main(push_tags)
push_tags = False
multiarch = False
for arg in sys.argv[1:]:
if arg == "--push-tags":
push_tags = True
elif arg == "--multiarch":
multiarch = True
main(push_tags, multiarch)
11 changes: 10 additions & 1 deletion docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ ARG USER=factorio
ARG GROUP=factorio
ARG PUID=845
ARG PGID=845
ARG BOX64_VERSION=v0.2.4

# version checksum of the archive to download
ARG VERSION
Expand Down Expand Up @@ -40,13 +41,21 @@ RUN set -ox pipefail \
&& mkdir -p /opt /factorio \
&& apt-get -q update \
&& DEBIAN_FRONTEND=noninteractive apt-get -qy install ca-certificates curl jq pwgen xz-utils --no-install-recommends \
&& rm -rf /var/lib/apt/lists/* \
&& curl -sSL "https://www.factorio.com/get-download/$VERSION/headless/linux64" -o "$archive" --retry $CURL_RETRIES\
&& echo "$SHA256 $archive" | sha256sum -c \
|| (sha256sum "$archive" && file "$archive" && exit 1) \
&& tar xf "$archive" --directory /opt \
&& chmod ugo=rwx /opt/factorio \
&& rm "$archive" \
&& if [[ "$(uname -m)" == "aarch64" ]]; then \
echo "installing ARM compatability layer" \
&& DEBIAN_FRONTEND=noninteractive apt-get -qy install unzip --no-install-recommends \
&& curl -LO https://github.com/ptitSeb/box64/releases/download/${BOX64_VERSION}/box64-GENERIC_ARM-RelWithDebInfo.zip \
&& unzip box64-GENERIC_ARM-RelWithDebInfo.zip -d /bin \
&& rm -f box64-GENERIC_ARM-RelWithDebInfo.zip \
&& chmod +x /bin/box64; \
fi \
&& rm -rf /var/lib/apt/lists/* \
&& ln -s "$SCENARIOS" /opt/factorio/scenarios \
&& ln -s "$SAVES" /opt/factorio/saves \
&& mkdir -p /opt/factorio/config/ \
Expand Down
14 changes: 9 additions & 5 deletions docker/files/docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,20 @@ if [[ ${UPDATE_MODS_ON_START:-} == "true" ]]; then
./docker-update-mods.sh
fi

EXEC=""
if [[ $(id -u) = 0 ]]; then
# Update the User and Group ID based on the PUID/PGID variables
usermod -o -u "$PUID" factorio
groupmod -o -g "$PGID" factorio
# Take ownership of factorio data if running as root
chown -R factorio:factorio "$FACTORIO_VOL"
# Drop to the factorio user
SU_EXEC="runuser -u factorio -g factorio --"
else
SU_EXEC=""
EXEC="runuser -u factorio -g factorio --"
fi
if [[ -f /bin/box64 ]]; then
# Use an emulator to run on ARM hosts
# this only gets installed when the target docker platform is linux/arm64
EXEC="$EXEC /bin/box64"
fi

sed -i '/write-data=/c\write-data=\/factorio/' /opt/factorio/config/config.ini
Expand All @@ -71,7 +75,7 @@ if [[ $GENERATE_NEW_SAVE == true ]]; then
if [[ -f "$SAVES/$SAVE_NAME.zip" ]]; then
echo "Map $SAVES/$SAVE_NAME.zip already exists, skipping map generation"
else
$SU_EXEC /opt/factorio/bin/x64/factorio \
$EXEC /opt/factorio/bin/x64/factorio \
--create "$SAVES/$SAVE_NAME.zip" \
--map-gen-settings "$CONFIG/map-gen-settings.json" \
--map-settings "$CONFIG/map-settings.json"
Expand Down Expand Up @@ -105,4 +109,4 @@ else
fi

# shellcheck disable=SC2086
exec $SU_EXEC /opt/factorio/bin/x64/factorio "${FLAGS[@]}" "$@"
exec $EXEC /opt/factorio/bin/x64/factorio "${FLAGS[@]}" "$@"

0 comments on commit 98d3e47

Please sign in to comment.