diff --git a/Dockerfile b/Dockerfile index 48be03f05f..aade2f6d9b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -91,5 +91,9 @@ COPY --chown=mambauser:mambauser dockerfiles/docker_tests /home/mambauser/Code/A COPY --chmod=755 dockerfiles/entrywrapper.sh /usr/local/bin/entrywrapper.sh COPY --chmod=644 dockerfiles/aliases.sh /etc/profile.d/aliases.sh COPY --chmod=755 dockerfiles/aliases_print.sh /usr/local/bin/aliases +RUN touch /home/mambauser/.bashrc && \ + grep -qxF 'source /etc/profile.d/aliases.sh' /home/mambauser/.bashrc || \ + echo 'source /etc/profile.d/aliases.sh' >> /home/mambauser/.bashrc +USER root ENTRYPOINT ["/usr/local/bin/entrywrapper.sh"] diff --git a/dockerfiles/entrywrapper.sh b/dockerfiles/entrywrapper.sh index 516783ba15..43cdde4c8e 100644 --- a/dockerfiles/entrywrapper.sh +++ b/dockerfiles/entrywrapper.sh @@ -1,9 +1,44 @@ #!/usr/bin/env bash set -euo pipefail -# 0) Only try chown if we're root (bind-mounts may be root-owned) -if [[ "$(id -u)" -eq 0 ]] && [[ ! -O /home/mambauser/Code ]]; then - chown -R mambauser:mambauser /home/mambauser/Code || true +# 0) If root, optionally remap mambauser UID/GID for bind mounts, then drop privileges. +if [[ "$(id -u)" -eq 0 ]]; then + if [[ -n "${PGID:-}" ]]; then + existing_group="" + if getent group "$PGID" >/dev/null; then + existing_group="$(getent group "$PGID" | cut -d: -f1)" + fi + if [[ -n "$existing_group" && "$existing_group" != "mambauser" ]]; then + echo "Error: requested PGID '$PGID' is already in use by group '$existing_group', cannot remap mambauser group." >&2 + exit 1 + fi + groupmod -g "$PGID" mambauser + fi + if [[ -n "${PUID:-}" ]]; then + current_uid="$(id -u mambauser)" + if [[ "$PUID" != "$current_uid" ]]; then + if getent passwd "$PUID" >/dev/null; then + echo "Error: Cannot remap mambauser to UID '$PUID' because it is already in use by another user." >&2 + exit 1 + fi + usermod -u "$PUID" mambauser + fi + fi + + if [[ -d /home/mambauser/Code ]]; then + if ! chown -R mambauser:mambauser /home/mambauser/Code; then + echo "warning: failed to change ownership of /home/mambauser/Code to mambauser:mambauser (read-only mount or permission issue?)" >&2 + fi + fi + if [[ -d /work ]]; then + if ! chown -R mambauser:mambauser /work; then + echo "warning: failed to change ownership of /work to mambauser:mambauser (read-only mount or permission issue?)" >&2 + fi + fi + + if [[ "${ENTRYWRAPPER_AS_USER:-0}" != "1" ]]; then + exec runuser -u mambauser -- env ENTRYWRAPPER_AS_USER=1 /usr/local/bin/entrywrapper.sh "$@" + fi fi # If running non-interactively at container root and /work exists; it will go there diff --git a/docs/source/docker.rst b/docs/source/docker.rst new file mode 100644 index 0000000000..84e1412e91 --- /dev/null +++ b/docs/source/docker.rst @@ -0,0 +1,71 @@ +.. _docker: + +Docker image +============ + +The published Docker image includes ARC and RMG along with convenience entrypoints. +Bind-mount your working directory and pass an input file path that exists inside +the container. For best write access on bind mounts, pass your host UID/GID as +``PUID``/``PGID`` (the entrypoint remaps the ``mambauser`` account). + +Run ARC non-interactively:: + + docker run --rm \ + -v "$PWD:/work" -w /work \ + -e PUID=$(id -u) -e PGID=$(id -g) \ + laxzal/arc:latest arc my_case/input.yml + +Run RMG non-interactively:: + + docker run --rm \ + -v "$PWD:/work" -w /work \ + -e PUID=$(id -u) -e PGID=$(id -g) \ + laxzal/arc:latest rmg my_case/input.py + +Manual RMG invocation:: + + docker run --rm \ + -v "$PWD:/work" -w /work \ + -e PUID=$(id -u) -e PGID=$(id -g) \ + laxzal/arc:latest \ + micromamba run -n rmg_env python /home/mambauser/Code/RMG-Py/rmg.py my_case/input.py + +Manual ARC invocation:: + + docker run --rm \ + -v "$PWD:/work" -w /work \ + -e PUID=$(id -u) -e PGID=$(id -g) \ + laxzal/arc:latest \ + micromamba run -n arc_env python /home/mambauser/Code/ARC/ARC.py my_case/input.yml + +Open an interactive shell:: + + docker run --rm -it \ + -v "$PWD:/work" -w /work \ + -e PUID=$(id -u) -e PGID=$(id -g) \ + laxzal/arc:latest + +For job submission, the scheduler client tools must be available in the container +or accessed via SSH on a remote host. + +Aliases in interactive shells +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When you open an interactive shell, the image provides these aliases:: + + rc # reload ~/.bashrc + rce, erc # edit ~/.bashrc with nano + + mamba, conda # micromamba + deact # micromamba deactivate + + rmge, arce # activate rmg_env / arc_env + + rmgcode # cd to /home/mambauser/Code/RMG-Py + dbcode # cd to /home/mambauser/Code/RMG-database + arcode # cd to /home/mambauser/Code/ARC + + rmg # run RMG with input.py, tee logs + arkane # run Arkane with input.py, tee logs + arc # run ARC with input.yml, tee logs + arcrestart # run ARC with restart.yml, tee logs diff --git a/docs/source/index.rst b/docs/source/index.rst index 21021ada2d..e3d6a5518c 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -35,6 +35,7 @@ Documentation Contents :maxdepth: 2 installation + docker running examples advanced diff --git a/docs/source/installation.rst b/docs/source/installation.rst index 0d32bd5b86..66d1ef4a04 100644 --- a/docs/source/installation.rst +++ b/docs/source/installation.rst @@ -11,6 +11,9 @@ Note: ARC was only tested on Linux (Ubuntu_ 18.04.1 and 20.04 LTS) and Mac machines. We don't expect it to work smoothly on Windows machines. +Note: + For a containerized setup, see the :ref:`Docker image ` documentation. + Note: These installation instructions assume you already have access to a server with a cluster scheduling software (ARC currently supports SGE, Slurm, PBS, and HTCondor) and with properly installed electronic structure software