diff --git a/app/build_containers.py b/app/build_containers.py index 7ecf4a8..04cecd6 100644 --- a/app/build_containers.py +++ b/app/build_containers.py @@ -83,7 +83,9 @@ def command(ctx, include, exclude): container_build_env = { "CERC_NPM_URL": "http://gitea.local:3000/api/packages/cerc-io/npm/", "CERC_NPM_AUTH_TOKEN": config("CERC_NPM_AUTH_TOKEN", default=""), - "CERC_REPO_BASE_DIR": dev_root_path + "CERC_REPO_BASE_DIR": dev_root_path, + "CERC_HOST_UID": f"{os.getuid()}", + "CERC_HOST_GID": f"{os.getgid()}" } def process_container(container): @@ -106,7 +108,7 @@ def command(ctx, include, exclude): build_command = os.path.join(container_build_dir, "default-build.sh") + f" {container}:local {repo_dir_or_build_dir}" if not dry_run: if verbose: - print(f"Executing: {build_command}") + print(f"Executing: {build_command} with environment: {container_build_env}") build_result = subprocess.run(build_command, shell=True, env=container_build_env) if verbose: print(f"Return code is: {build_result.returncode}") diff --git a/app/build_npms.py b/app/build_npms.py index 83f87ed..877916b 100644 --- a/app/build_npms.py +++ b/app/build_npms.py @@ -116,7 +116,11 @@ def command(ctx, include, exclude): if not dry_run: if verbose: print(f"Executing: {build_command}") - envs = {"CERC_NPM_AUTH_TOKEN": npm_registry_url_token} | ({"CERC_SCRIPT_DEBUG": "true"} if debug else {}) + # Originally we used the PEP 584 merge operator: + # envs = {"CERC_NPM_AUTH_TOKEN": npm_registry_url_token} | ({"CERC_SCRIPT_DEBUG": "true"} if debug else {}) + # but that isn't available in Python 3.8 (default in Ubuntu 20) so for now we use dict.update: + envs = {"CERC_NPM_AUTH_TOKEN": npm_registry_url_token} + envs.update({"CERC_SCRIPT_DEBUG": "true"} if debug else {}) try: docker.run(builder_js_image_name, remove=True, diff --git a/app/data/container-build/cerc-builder-js/Dockerfile b/app/data/container-build/cerc-builder-js/Dockerfile index 9f46037..35c9a97 100644 --- a/app/data/container-build/cerc-builder-js/Dockerfile +++ b/app/data/container-build/cerc-builder-js/Dockerfile @@ -1,14 +1,30 @@ # Originally from: https://github.com/devcontainers/images/blob/main/src/javascript-node/.devcontainer/Dockerfile +# Which depends on: https://github.com/nodejs/docker-node/blob/main/Dockerfile-debian.template # [Choice] Node.js version (use -bullseye variants on local arm64/Apple Silicon): 18, 16, 14, 18-bullseye, 16-bullseye, 14-bullseye, 18-buster, 16-buster, 14-buster ARG VARIANT=16-bullseye FROM node:${VARIANT} +# Set these args to change the uid/gid for the base container's "node" user to match that of the host user (so bind mounts work as expected). +ARG CERC_HOST_UID=1000 +ARG CERC_HOST_GID=1000 +# Make these values available at runtime to allow a consistency check. +ENV HOST_UID=${CERC_HOST_UID} +ENV HOST_GID=${CERC_HOST_GID} + ARG USERNAME=node ARG NPM_GLOBAL=/usr/local/share/npm-global # Add NPM global to PATH. ENV PATH=${NPM_GLOBAL}/bin:${PATH} +RUN \ + if [ ${CERC_HOST_GID} -ne 1000 ] ; then \ + groupmod -g ${CERC_HOST_GID} ${USERNAME} ; \ + fi \ + && if [ ${CERC_HOST_UID} -ne 1000 ] ; then \ + usermod -u ${CERC_HOST_UID} -g ${CERC_HOST_GID} ${USERNAME} && chown ${CERC_HOST_UID}:${CERC_HOST_GID} /home/${USERNAME} ; \ + fi + RUN \ # Configure global npm install location, use group to adapt to UID/GID changes if ! cat /etc/group | grep -e "^npm:" > /dev/null 2>&1; then groupadd -r npm; fi \ @@ -39,6 +55,7 @@ RUN mkdir /scripts COPY build-npm-package.sh /scripts COPY yarn-local-registry-fixup.sh /scripts COPY build-npm-package-local-dependencies.sh /scripts +COPY check-uid.sh /scripts ENV PATH="${PATH}:/scripts" COPY entrypoint.sh . diff --git a/app/data/container-build/cerc-builder-js/check-uid.sh b/app/data/container-build/cerc-builder-js/check-uid.sh new file mode 100755 index 0000000..a8cbc32 --- /dev/null +++ b/app/data/container-build/cerc-builder-js/check-uid.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# Make the container usable for uid/gid != 1000 +if [[ -n "$CERC_SCRIPT_DEBUG" ]]; then + set -x +fi +current_uid=$(id -u) +current_gid=$(id -g) +# Don't check if running as root +if [[ ${current_uid} == 0 ]]; then + exit 0 +fi +# Check the current uid/gid vs the uid/gid used to build the container. +# We do this because both bind mounts and npm tooling require the uid/gid to match. +if [[ ${current_gid} != ${HOST_GID} ]]; then + echo "Warning: running with gid: ${current_gid} which is not the gid for which this container was built (${HOST_GID})" + exit 0 +fi +if [[ ${current_uid} != ${HOST_UID} ]]; then + echo "Warning: running with gid: ${current_uid} which is not the uid for which this container was built (${HOST_UID})" + exit 0 +fi diff --git a/app/data/container-build/cerc-builder-js/entrypoint.sh b/app/data/container-build/cerc-builder-js/entrypoint.sh index 311cb8c..ab80737 100755 --- a/app/data/container-build/cerc-builder-js/entrypoint.sh +++ b/app/data/container-build/cerc-builder-js/entrypoint.sh @@ -1,2 +1,3 @@ #!/bin/sh +/scripts/check-uid.sh exec "$@" diff --git a/app/data/container-build/default-build.sh b/app/data/container-build/default-build.sh index 3d5d991..c52dd04 100755 --- a/app/data/container-build/default-build.sh +++ b/app/data/container-build/default-build.sh @@ -11,4 +11,4 @@ fi image_tag=$1 build_dir=$2 echo "Building ${image_tag} in ${build_dir}" -docker build -t ${image_tag} ${build_dir} +docker build -t ${image_tag} --build-arg CERC_HOST_UID=${CERC_HOST_UID} --build-arg CERC_HOST_GID=${CERC_HOST_GID} ${build_dir}