mirror of
https://github.com/freedomofpress/dangerzone.git
synced 2025-04-28 18:02:38 +02:00

There are times where we may want to build the container image for testing, but compression takes too much time. If we don't plan to use this image for production builds, we can specify instead a compression level that is so low, that the image will be compressed instantly. In this commit, we allow the user to specify the Gzip compression level, and even set it to 0. The default will always be 9, so that we don't make a mistake during release.
132 lines
3.8 KiB
Python
132 lines
3.8 KiB
Python
import argparse
|
|
import gzip
|
|
import os
|
|
import platform
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
BUILD_CONTEXT = "dangerzone/"
|
|
TAG = "dangerzone.rocks/dangerzone:latest"
|
|
REQUIREMENTS_TXT = "container-pip-requirements.txt"
|
|
if platform.system() in ["Darwin", "Windows"]:
|
|
CONTAINER_RUNTIME = "docker"
|
|
elif platform.system() == "Linux":
|
|
CONTAINER_RUNTIME = "podman"
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument(
|
|
"--runtime",
|
|
choices=["docker", "podman"],
|
|
default=CONTAINER_RUNTIME,
|
|
help=f"The container runtime for building the image (default: {CONTAINER_RUNTIME})",
|
|
)
|
|
parser.add_argument(
|
|
"--no-save",
|
|
action="store_true",
|
|
help="Do not save the container image as a tarball in share/container.tar.gz",
|
|
)
|
|
parser.add_argument(
|
|
"--compress-level",
|
|
type=int,
|
|
choices=range(0, 10),
|
|
default=9,
|
|
help="The Gzip compression level, from 0 (lowest) to 9 (highest, default)",
|
|
)
|
|
args = parser.parse_args()
|
|
|
|
print("Exporting container pip dependencies")
|
|
with ContainerPipDependencies():
|
|
print("Pulling base image")
|
|
subprocess.run(
|
|
[
|
|
args.runtime,
|
|
"pull",
|
|
"alpine:latest",
|
|
],
|
|
check=True,
|
|
)
|
|
|
|
print("Building container image")
|
|
subprocess.run(
|
|
[
|
|
args.runtime,
|
|
"build",
|
|
BUILD_CONTEXT,
|
|
"--build-arg",
|
|
f"REQUIREMENTS_TXT={REQUIREMENTS_TXT}",
|
|
"-f",
|
|
"Dockerfile",
|
|
"--tag",
|
|
TAG,
|
|
],
|
|
check=True,
|
|
)
|
|
|
|
if not args.no_save:
|
|
print("Saving container image")
|
|
cmd = subprocess.Popen(
|
|
[
|
|
CONTAINER_RUNTIME,
|
|
"save",
|
|
TAG,
|
|
],
|
|
stdout=subprocess.PIPE,
|
|
)
|
|
|
|
print("Compressing container image")
|
|
chunk_size = 4 << 20
|
|
with gzip.open(
|
|
"share/container.tar.gz",
|
|
"wb",
|
|
compresslevel=args.compress_level,
|
|
) as gzip_f:
|
|
while True:
|
|
chunk = cmd.stdout.read(chunk_size)
|
|
if len(chunk) > 0:
|
|
gzip_f.write(chunk)
|
|
else:
|
|
break
|
|
cmd.wait(5)
|
|
|
|
print("Looking up the image id")
|
|
image_id = subprocess.check_output(
|
|
[
|
|
args.runtime,
|
|
"image",
|
|
"list",
|
|
"--format",
|
|
"{{.ID}}",
|
|
TAG,
|
|
],
|
|
text=True,
|
|
)
|
|
with open("share/image-id.txt", "w") as f:
|
|
f.write(image_id)
|
|
|
|
|
|
class ContainerPipDependencies:
|
|
"""Generates PIP dependencies within container"""
|
|
|
|
def __enter__(self):
|
|
try:
|
|
container_requirements_txt = subprocess.check_output(
|
|
["poetry", "export", "--only", "container"], universal_newlines=True
|
|
)
|
|
except subprocess.CalledProcessError as e:
|
|
print("FAILURE", e.returncode, e.output)
|
|
print(f"REQUIREMENTS: {container_requirements_txt}")
|
|
# XXX Export container dependencies and exclude pymupdfb since it is not needed in container
|
|
req_txt_pymupdfb_stripped = container_requirements_txt.split("pymupdfb")[0]
|
|
with open(Path(BUILD_CONTEXT) / REQUIREMENTS_TXT, "w") as f:
|
|
f.write(req_txt_pymupdfb_stripped)
|
|
|
|
def __exit__(self, exc_type, exc_value, exc_tb):
|
|
print("Leaving the context...")
|
|
os.remove(Path(BUILD_CONTEXT) / REQUIREMENTS_TXT)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|