mirror of
				https://github.com/factoriotools/factorio-docker.git
				synced 2025-10-31 00:48:07 +01:00 
			
		
		
		
	add support for ARM (#485)
* build and run on arm64 * multiarch docker build * add ARM64 warning to README.md
This commit is contained in:
		
							
								
								
									
										4
									
								
								.github/workflows/docker.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/docker.yml
									
									
									
									
										vendored
									
									
								
							| @@ -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
									
								
								.github/workflows/docker_push.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/docker_push.yml
									
									
									
									
										vendored
									
									
								
							| @@ -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 | ||||
|   | ||||
| @@ -1,5 +1,8 @@ | ||||
| # Factorio [](https://hub.docker.com/r/factoriotools/factorio/) [](https://hub.docker.com/r/factoriotools/factorio/) [](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 --> | ||||
|   | ||||
							
								
								
									
										87
									
								
								build.py
									
									
									
									
									
								
							
							
						
						
									
										87
									
								
								build.py
									
									
									
									
									
								
							| @@ -7,14 +7,40 @@ import shutil | ||||
| 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: | ||||
| @@ -22,6 +48,30 @@ def build_dockerfile(sha256, version, tags): | ||||
|         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"] | ||||
| @@ -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) | ||||
|  | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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 | ||||
| @@ -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/ \ | ||||
|   | ||||
| @@ -43,6 +43,7 @@ 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 | ||||
| @@ -50,9 +51,12 @@ if [[ $(id -u) = 0 ]]; then | ||||
|   # 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 | ||||
| @@ -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" | ||||
| @@ -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[@]}" "$@" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user