-
Notifications
You must be signed in to change notification settings - Fork 21
dev: add docker developer container for easier installation and usage #305
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 4 commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
152742a
docker: add dev-container Dockerfile and scripts
IvanGrigorik fdd200a
dev-container: finalaize container structure and user prompts
IvanGrigorik 7f7ced7
docker: change port exposure in order to correctly ssh straight into …
IvanGrigorik 931d968
add pykokkos into devcontainer
IvanGrigorik c883081
change EOF format
IvanGrigorik 97e7a2f
change EOF format
IvanGrigorik ee4f50a
remove deprecated Dockerfile
IvanGrigorik 2fbfeb8
sync up with `main`
IvanGrigorik c6903ea
Merge branch 'main' into grigorik/docker-devcontainer
IvanGrigorik 5c66b36
update docker installation
IvanGrigorik d72ab1b
Merge branch 'main' into grigorik/docker-devcontainer
IvanGrigorik 4d5d04f
merge conflict resolution
IvanGrigorik 1733c7e
add flexible NVIDIA docker container with custom kernel
IvanGrigorik c679035
Merge branch 'grigorik/docker-devcontainer' of github.com:kokkos/pyko…
IvanGrigorik 90f5153
add template for secrets
IvanGrigorik 32c443e
add default template proper handling
IvanGrigorik ccb78f5
add pykokkos installation after base install
IvanGrigorik 49bf16c
shellcheck warns fix
IvanGrigorik 0aa1fc7
add workflow to check devcontainer linting errors, shell errors and b…
IvanGrigorik e52f2d0
fix shellcheck warns
IvanGrigorik 2ea84b3
fix hadolint docker container issues
IvanGrigorik 8f89922
fix shellcheck warns
IvanGrigorik 1c19d31
add wget to install list
IvanGrigorik 9e269c9
address all shellcheck warns
IvanGrigorik File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -45,3 +45,6 @@ Sessionx.vim | |
| tags | ||
| # Persistent undo | ||
| [._]*.un~ | ||
|
|
||
| # Docker files and secrets | ||
| dev-container/secrets/ | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| FROM nvidia/cuda:12.4.1-devel-ubuntu22.04 | ||
|
|
||
| ARG USERNAME | ||
| ENV username=${USERNAME} | ||
|
|
||
| # Dependencies installation | ||
| RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \ | ||
| build-essential \ | ||
| micro \ | ||
| nano \ | ||
| git \ | ||
| openssh-server \ | ||
| && rm -rf /var/lib/apt/lists/* | ||
|
|
||
| # Read secrets and create user with home directory | ||
| RUN --mount=type=secret,id=username \ | ||
| --mount=type=secret,id=password \ | ||
| --mount=type=secret,id=ssh_key \ | ||
| export NAME=$(cat /run/secrets/username) && \ | ||
| export PASSWORD=$(cat /run/secrets/password) && \ | ||
| export SSH_PUB_KEY=$(cat /run/secrets/ssh_key) && \ | ||
| useradd -m -u 1000 -s /bin/bash ${NAME} && \ | ||
| echo "${NAME}:${PASSWORD}" | chpasswd && \ | ||
| echo "root:${PASSWORD}" | chpasswd && \ | ||
| usermod -aG sudo ${NAME} && \ | ||
| chown -R ${NAME}:${NAME} /home/${NAME} && \ | ||
| echo "${NAME} ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers && \ | ||
| echo "${NAME}" > /tmp/username | ||
|
|
||
| # Configure SSH permissions for devcontainer | ||
| RUN mkdir /var/run/sshd && \ | ||
| sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin no/' /etc/ssh/sshd_config && \ | ||
| sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config | ||
|
|
||
| # Add SSH public key if provided | ||
| RUN --mount=type=secret,id=ssh_key \ | ||
| SSH_PUB_KEY=$(cat /run/secrets/ssh_key) && \ | ||
| mkdir -p /home/${username}/.ssh/ && \ | ||
| if [ -n "$SSH_PUB_KEY" ]; then \ | ||
| echo "$SSH_PUB_KEY" >> /home/${username}/.ssh/authorized_keys; \ | ||
| fi && \ | ||
| chmod 700 /home/${username}/.ssh/ && \ | ||
| chown -R ${username}:${username} /home/${username}/.ssh/ && \ | ||
| if [ -f /home/${username}/.ssh/authorized_keys ]; then \ | ||
| chmod 600 /home/${username}/.ssh/authorized_keys; \ | ||
| fi | ||
|
|
||
| # Set up custom entrypoint | ||
| WORKDIR /home/${username}/ | ||
| COPY dev-container/scripts/custom-entrypoint.sh /opt/custom-entrypoint.sh | ||
| RUN chmod +x /opt/custom-entrypoint.sh | ||
|
|
||
| # Set up and initialize conda environment | ||
| RUN echo "export condaPath=/home/${username}/miniconda3/bin/" >> /tmp/conda_env | ||
| ENV condaPath="/home/${username}/miniconda3/bin" | ||
| RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh && \ | ||
| bash miniconda.sh -b -p /home/${username}/miniconda3 && \ | ||
| rm -f miniconda.sh && \ | ||
| chown -R ${username}:${username} /home/${username}/miniconda3/ | ||
|
|
||
| # Initialize user's conda environment, TOS agreements | ||
| USER ${username} | ||
| WORKDIR /home/${username}/ | ||
| # Initialize conda in bash and ensure it's loaded in every shell | ||
| RUN ${condaPath}/conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/main && \ | ||
| ${condaPath}/conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/r && \ | ||
| ${condaPath}/conda init | ||
|
|
||
| # Clone myself to this container | ||
| RUN git clone https://github.com/kokkos/pykokkos.git | ||
| RUN git clone https://github.com/kokkos/pykokkos-base.git | ||
|
|
||
| # Expose port in order to be able to connect from IDEs | ||
| USER root | ||
| EXPOSE 2222 | ||
|
|
||
| # Add ~/.local/bin to PATH (for pip installs etc.) | ||
| RUN echo "export PATH=\"/home/${username}/miniconda3/bin:/home/${username}/miniconda3/condabin:/home/${username}/.local/bin:/usr/local/nvidia/bin:/usr/local/cuda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"" >> /home/${username}/.bashrc | ||
|
|
||
| ENTRYPOINT ["/opt/custom-entrypoint.sh"] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| #!/bin/bash | ||
|
|
||
| # Get absolute paths for all directories we need | ||
| SCRIPT_PATH=$(readlink -f "${BASH_SOURCE[0]}") | ||
| CONTAINER_DIR=$(dirname "$SCRIPT_PATH") | ||
| SCRIPTS_DIR="${CONTAINER_DIR}/scripts" | ||
| PROJECT_ROOT=$(dirname "$CONTAINER_DIR") | ||
|
|
||
| pushd "$CONTAINER_DIR" &> /dev/null | ||
|
|
||
| # Secrets initialization | ||
| bash "${SCRIPTS_DIR}/init.sh" | ||
|
|
||
| # Container name initialization | ||
| DEFAULT_CONTAINER_NAME="pykokkos-dev-container" | ||
| echo "Container name configuration. Press 'Enter' to use default" | ||
| read -p "Enter container name [${DEFAULT_CONTAINER_NAME}]: " CONTAINER_NAME | ||
| CONTAINER_NAME=${CONTAINER_NAME:-$DEFAULT_CONTAINER_NAME} | ||
| USERNAME="$(cat ${CONTAINER_DIR}/secrets/username)" | ||
|
|
||
| # Docker container build (add secret to use in `RUN` commands and arg to use in | ||
| # Dockerfile commands) | ||
| echo "Building docker container: ${CONTAINER_NAME}" | ||
|
|
||
| docker build \ | ||
| --no-cache \ | ||
| --build-arg USERNAME="${USERNAME}" \ | ||
| --secret id=username,src="${CONTAINER_DIR}/secrets/username" \ | ||
| --secret id=password,src="${CONTAINER_DIR}/secrets/pass" \ | ||
| --secret id=ssh_key,src="${CONTAINER_DIR}/secrets/sha" \ | ||
| -t "${CONTAINER_NAME}:latest" \ | ||
| -f "${CONTAINER_DIR}/Dockerfile" \ | ||
| "${PROJECT_ROOT}" | ||
|
|
||
| if [ $? != 0 ]; then | ||
| exit | ||
| fi | ||
| # Stopping same environment, if exists | ||
| echo "Stopping ${CONTAINER_NAME}" | ||
| docker stop "${CONTAINER_NAME}" | ||
|
|
||
| echo "Removing ${CONTAINER_NAME}" | ||
| docker rm "${CONTAINER_NAME}" | ||
|
|
||
| docker run -dit \ | ||
| --gpus all \ | ||
| --name "${CONTAINER_NAME}" \ | ||
| -p 2222:2222 \ | ||
| --restart unless-stopped \ | ||
| "${CONTAINER_NAME}" | ||
|
|
||
| function farewell { | ||
| echo "##################" | ||
| echo "Container started." | ||
| echo "To access container from terminal, enter: " | ||
| echo "> docker exec -it -u ${USERNAME} ${CONTAINER_NAME} bash" | ||
| echo "To access sudo mode, enter 'su' and password, entered/generated above." | ||
| } | ||
|
|
||
| # Call farewell function at the end | ||
| farewell | ||
| popd |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| #!/bin/bash | ||
|
|
||
| /usr/sbin/sshd -D -p 2222 & | ||
| /opt/nvidia/nvidia_entrypoint.sh |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| #!/bin/bash | ||
| # Main initialization script. | ||
| # Initializes devcontainer username, password, ssh keys and number of processors, during pykokkos-base installation phase | ||
| SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) | ||
| CONTAINER_DIR="$SCRIPT_DIR/../" | ||
|
|
||
| NAME_PATH="${CONTAINER_DIR}/secrets/username" | ||
| PASS_PATH="${CONTAINER_DIR}/secrets/pass" | ||
| SHA_KEY_PATH="${CONTAINER_DIR}/secrets/sha" | ||
| PAR_PATH="${CONTAINER_DIR}/secrets/parallel" | ||
|
|
||
| # Initialize default values | ||
| DEFAULT_USERNAME="pykokkos-dev" | ||
| DEFAULT_PASSWORD=$(openssl rand -base64 16 | tr -d "=+/" | cut -c1-16) | ||
| DEFAULT_SSH_KEY="" | ||
| DEFAULT_PARALLEL_LEVEL=$(nproc) | ||
|
|
||
| # Create secrets directory if it doesn't exist | ||
| mkdir -p "${CONTAINER_DIR}/secrets" | ||
|
|
||
| # Initialize secret files with defaults if they don't exist | ||
| if [ ! -f "${NAME_PATH}" ]; then | ||
| echo -n "${DEFAULT_USERNAME}" > "${NAME_PATH}" | ||
| fi | ||
| if [ ! -f "${PASS_PATH}" ]; then | ||
| echo -n "${DEFAULT_PASSWORD}" > "${PASS_PATH}" | ||
| fi | ||
| if [ ! -f "${SHA_KEY_PATH}" ]; then | ||
| echo -n "${DEFAULT_SSH_KEY}" > "${SHA_KEY_PATH}" | ||
| fi | ||
| if [ ! -f "${PAR_PATH}" ]; then | ||
| echo -n "${DEFAULT_PARALLEL_LEVEL}" > "${PAR_PATH}" | ||
| fi | ||
|
|
||
| # Secrets input | ||
| echo "Secrets initialization. Press 'Enter' to use [default values]" | ||
| read -p "Enter username for dev container [${DEFAULT_USERNAME}]: " dev_name | ||
| dev_name=${dev_name:-$DEFAULT_USERNAME} | ||
|
|
||
| read -p "Enter password for dev container [randomly generated]: " -s dev_pass | ||
| echo | ||
| dev_pass=${dev_pass:-$DEFAULT_PASSWORD} | ||
|
|
||
| read -p "Enter public SSH key for dev container [none]: " dev_ssh_pubkey | ||
| dev_ssh_pubkey=${dev_ssh_pubkey:-$DEFAULT_SSH_KEY} | ||
|
|
||
| read -p "Enter cmake parallel level for build [${DEFAULT_PARALLEL_LEVEL}]: " dev_parallel | ||
| dev_parallel=${dev_parallel:-$DEFAULT_PARALLEL_LEVEL} | ||
|
|
||
| # Put secrets into secret files | ||
| echo -n "${dev_name}" > "${NAME_PATH}" | ||
| echo -n "${dev_ssh_pubkey}" > "${SHA_KEY_PATH}" | ||
| echo -n "${dev_pass}" > "${PASS_PATH}" | ||
| echo -n "${dev_parallel}" > "${PAR_PATH}" | ||
|
|
||
| # Output default and autogenerated variables, if some variables are not initialized | ||
| echo "Username set: ${dev_name}" | ||
| if [ "${dev_pass}" = "${DEFAULT_PASSWORD}" ]; then | ||
| echo "Password set (randomly generated): ${DEFAULT_PASSWORD}" | ||
| else | ||
| echo "Password set" | ||
| fi | ||
| if [ -n "${dev_ssh_pubkey}" ]; then | ||
| echo "SSH key set" | ||
| else | ||
| echo "No SSH key provided" | ||
| fi | ||
|
|
||
| # Set secure permissions (600) of all secrets | ||
| chmod 600 "${NAME_PATH}" "${PASS_PATH}" "${SHA_KEY_PATH}" "${PAR_PATH}" 2>/dev/null || true | ||
| echo "Secrets initialization complete" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| #!/bin/bash | ||
|
|
||
|
|
||
|
|
||
| # Show warning about processor usage | ||
| echo "WARNING: Using too many processors for building may slow down your system significantly." | ||
| echo "Available processors: $(nproc)" | ||
|
|
||
| # Determine PARALLEL_LEVEL: | ||
| # - prefer environment variable PARALLEL_LEVEL if set and >0 (can be baked-in via Docker ARG/ENV) | ||
| # - otherwise fall back to container/host nproc | ||
| if [ -n "${PARALLEL_LEVEL:-}" ] && [ "${PARALLEL_LEVEL}" -gt 0 ] 2>/dev/null; then | ||
| PARALLEL_LEVEL="${PARALLEL_LEVEL}" | ||
| else | ||
| read -p "Enter number of processors to use [default: $(nproc)]: " USER_PARALLEL | ||
| PARALLEL_LEVEL=${USER_PARALLEL:-$(nproc)} | ||
| fi | ||
|
|
||
| pushd "/home/${USERNAME}" | ||
| # Prefer the Miniconda installed in the user's home; fall back to any `conda` in PATH. | ||
| if [ -n $(which conda) ]; then | ||
| echo "ERROR: conda not found." | ||
| dirs -c | ||
| exit 1 | ||
| fi | ||
|
|
||
| # Begin pykokkos-base installation process | ||
| git clone https://github.com/kokkos/pykokkos-base.git | ||
| pushd pykokkos-base | ||
|
|
||
| # Create the conda environment using the resolved conda command | ||
| "${CONDA_CMD}" create -y --name pyk --file requirements.txt python=3.11 | ||
| "${CONDA_CMD}" activate pyk | ||
|
|
||
| python setup.py install -- -DENABLE_LAYOUTS=ON -DENABLE_MEMORY_TRAITS=OFF \ | ||
| -DCMAKE_BUILD_PARALLEL_LEVEL=${PARALLEL_LEVEL} \ | ||
| -DENABLE_VIEW_RANKS=4 \ | ||
| -DENABLE_CUDA=ON -DKokkos_ENABLE_CUDA=ON \ | ||
| -DENABLE_OPENMP=ON -DKokkos_ENABLE_OPENMP=ON \ | ||
| -DENABLE_THREADS=OFF \ | ||
| -DCMAKE_CXX_STANDARD=20 \ | ||
| -DCMAKE_CXX_COMPILER=/usr/bin/c++ -DCMAKE_C_COMPILER=/usr/bin/cc -DCMAKE_POLICY_VERSION_MINIMUM=3.5 | ||
|
|
||
| popd | ||
| dirs -c | ||
|
|
||
| # Make hidden file to check that pykokkos is installed now | ||
| # touch /home/"${USERNAME}"/.pyk-installed |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.