Skip to content

Instantly share code, notes, and snippets.

@lrtfm
Last active October 4, 2024 09:56
Show Gist options
  • Save lrtfm/93d55c6d8d5bc92d2c7551dd0048fd4f to your computer and use it in GitHub Desktop.
Save lrtfm/93d55c6d8d5bc92d2c7551dd0048fd4f to your computer and use it in GitHub Desktop.
Run command in container of firedrake or firedrake-complex
#!/bin/bash
set -e
TOOL=${TOOL:-docker} # Set TOOL to 'docker' by default. Change it to 'podman' if needed.
BASE_IMAGE=${BASE_IMAGE:-firedrakeproject/firedrake}
RUN_ARGS=${RUN_ARGS:---rm}
if [[ "$TOOL" == "docker" ]]; then
BUILD_ARGS="${BUILD_ARGS:---network=host}"
elif [[ "$TOOL" == "podman" ]]; then
BUILD_ARGS="${BUILD_ARGS} --format docker" # Use Docker format for Podman
else
echo "Error: TOOL must be set to either 'docker' or 'podman'."
exit 1
fi
usage() {
PROG=$(basename "$0")
echo
echo "Usage: $PROG command [args...]"
echo "Run a command inside the Firedrake container."
echo
echo "Examples (Scalar type: real):"
echo " $PROG python my-python-file.py"
echo " $PROG mpiexec -n 16 python my-python-file.py"
echo
echo "To use Podman instead of Docker:"
echo " TOOL=podman $PROG python my-python-file.py"
echo " TOOL=podman $PROG mpiexec -n 16 python my-python-file.py"
echo
echo "Run command with debug messages enabled:"
echo " DEBUG=Y $PROG python my-python-file.py"
echo
echo "Force a rebuild of the container image:"
echo " FORCE_BUILD=Y $PROG"
echo
if [[ "$TOOL" == "docker" ]]; then
echo "Customize build arguments for '$TOOL build' (Default: '--network=host'):"
echo " FORCE_BUILD=Y BUILD_ARGS=\"--no-cache --network=host\" $PROG"
else
echo "Customize build arguments for '$TOOL build':"
echo " TOOL=podman FORCE_BUILD=Y BUILD_ARGS=\"--no-cache\" $PROG"
fi
echo
echo "Example for complex scalar type:"
echo " BASE_IMAGE=firedrakeproject/firedrake-complex $PROG python my-python-file.py"
echo
exit 1
}
if [[ "x$1" =~ x-h|x--help ]]; then
usage
fi
is_true () {
_VAL=$(echo "${1:-N}" | tr '[:upper:]' '[:lower:]')
[[ ${_VAL} =~ [1-9]|t|true|y|yes|on ]] && return 0 # true
return 1 # false
}
print_msg () {
MSG=$1
TERM_WIDTH=${TERM_WIDTH:-$(tput cols)}
PADDING_WIDTH=$(( (${TERM_WIDTH} - 2 - ${#MSG})/2 ))
PADDING=$(for i in $(seq 1 ${PADDING_WIDTH}); do echo -n =; done)
echo "$PADDING $MSG $PADDING"$([ $(( ${#MSG}%2 )) == 1 ] && echo -n = || echo -n "")
}
TERM_WIDTH=80
FORCE_BUILD=$( is_true ${FORCE_BUILD} && echo Y || echo N)
DEBUG=$( is_true ${DEBUG:-$FORCE_BUILD} && echo "" || echo ":" )
${DEBUG} print_msg "DEBUG VARS BEGIN"
${DEBUG} echo -e "VARs:\n\tDEBUG: \"${DEBUG:-Y}\"\n\tFORCE_BUILD: \"$FORCE_BUILD\""
${DEBUG} print_msg "DEBUG VARS END"
if [[ "x$FDUTILS_COMMIT" != "x" ]]; then
CHECKOUT_COMMIT="&& git checkout $FDUTILS_COMMIT"
fi
create_dockerfile () {
_BASE_IMAGE=$1
_DOCKERFILE=$2
cat <<EOF > $_DOCKERFILE
FROM $_BASE_IMAGE
USER root
RUN echo -e "[safe]\n\tdirectory = *\n" >> /etc/gitconfig
USER firedrake
WORKDIR /home/firedrake
RUN bash -c ". /home/firedrake/firedrake/bin/activate && \\
pip install pqdm gmsh siphash24 && \\
git clone https://github.com/lrtfm/fdutils.git && \\
cd fdutils $CHECKOUT_COMMIT && make develop"
RUN bash -c "sed -i.bak -e 's/^.*simplefilter.*$//g' firedrake/src/firedrake/firedrake/checkpointing.py"
EOF
${DEBUG} print_msg "THE DOCKER FILE BEGIN"
${DEBUG} cat $_DOCKERFILE
${DEBUG} print_msg "THE DOCKER FILE END"
}
if [[ "x$IMAGE" == "x" ]]; then
BASE_NAME_NOTAG=${BASE_IMAGE//:*/}
IMAGE_NAME=${BASE_NAME_NOTAG//*\//}-$(id -u -n)
if ! ${TOOL} image inspect $BASE_IMAGE > /dev/null 2>&1; then
${TOOL} pull $BASE_IMAGE
fi
DATE_TAG=$(${TOOL} inspect -f '{{ .Created }}' $BASE_IMAGE | sed -E -e 's/(T| ).*//' -e 's/-//g')
if ! ${TOOL} image inspect $IMAGE_NAME:$DATE_TAG > /dev/null 2>&1; then
TARGET_EXIST="N"
else
TARGET_EXIST="Y"
fi
if [[ "$TARGET_EXIST" == "N" || "$FORCE_BUILD" == "Y" ]]; then
TEMP_DOCKERFILE=$(mktemp .Dockerfile.XXXXXXXXXXXXXXXX)
trap 'rm -f -- "$TEMP_DOCKERFILE"' EXIT
create_dockerfile $BASE_IMAGE $TEMP_DOCKERFILE
if [[ "$TARGET_EXIST" == "Y" ]]; then
${TOOL} tag $IMAGE_NAME:$DATE_TAG $IMAGE_NAME:$DATE_TAG-bak-$(date +%Y%m%d-%H%M%S)
fi
${DEBUG} print_msg "BUILD BEGIN"
echo "${TOOL} build $BUILD_ARGS -t $IMAGE_NAME:$DATE_TAG -f $TEMP_DOCKERFILE ."
${TOOL} build $BUILD_ARGS -t $IMAGE_NAME:$DATE_TAG -f $TEMP_DOCKERFILE .
${DEBUG} print_msg "BUILD END"
fi
IMAGE=$IMAGE_NAME:$DATE_TAG
fi
FD_INFO=$(${TOOL} run --rm $IMAGE bash -c 'echo $(id -u)\;$(id -g -n)\;$HOME\;$PATH\;')
IFS=';' read -r FD_UID FD_GNAME FD_HOME FD_PATH <<< "$FD_INFO"
[[ $(id -u) != ${FD_UID} ]] && FD_HOME=/work
FD_ENV=/home/firedrake/firedrake
FD_PATH=${FD_ENV}/bin:${FD_PATH}
SET_USER=${SET_USER:-$(id -u):$(id -g)}
ADD_GROUP=${ADD_GROUP:-$FD_GNAME}
${DEBUG} print_msg "THE CMD BEGIN"
${DEBUG} echo -ne "IMAGE:\n\t"; ${DEBUG} echo "$IMAGE"
${DEBUG} echo -ne "COMMAND:\n\t\x60"; ${DEBUG} echo -n "$@"; ${DEBUG} echo -e "\x27"
${DEBUG} echo -ne "HOME:\n\t"; ${DEBUG} echo "$FD_HOME"
${DEBUG} echo -ne "PATH:\n\t"; ${DEBUG} echo "$FD_PATH"
${DEBUG} echo -ne "SET_USER:\n\t"; ${DEBUG} echo "$SET_USER"
${DEBUG} echo -ne "ADD_GROUP:\n\t"; ${DEBUG} echo "$ADD_GROUP"
${DEBUG} print_msg "THE CMD END"
if [[ $# -eq 0 ]]; then
usage
fi
if [[ "$TOOL" == "docker" ]]; then
PERMISSION_ARGS="-u ${SET_USER} --group-add ${ADD_GROUP}"
elif [[ "$TOOL" == "podman" ]]; then
PERMISSION_ARGS="--security-opt label=disable --userns keep-id:uid=1000,gid=1000"
fi
${TOOL} run ${RUN_ARGS} ${PERMISSION_ARGS} \
-ti -v $(pwd):/work -w /work \
-e HOME=${FD_HOME} \
-e PATH=${FD_PATH} \
-e VIRTUAL_ENV=${FD_ENV} \
-e PYOP2_CACHE_DIR=/work/.cache \
-e FIREDRAKE_TSFC_KERNEL_CACHE_DIR=/work/.cache \
$IMAGE \
"$@"
@lrtfm
Copy link
Author

lrtfm commented Apr 16, 2024

This aims to address inconsistent permission issues of the shared folders in the Firedrake container.

  1. Download the script

    curl -O https://gist.github.com/lrtfm/93d55c6d8d5bc92d2c7551dd0048fd4f/raw/firedrake-run
    
  2. Add exec permission

    chmod +x firedrake-run
    
  3. Now, you can run firedrake script

    ./firedrake-run python my-script.py
    

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment