From bd9e43716a9683adcd287a5badfc609e4bd2bc84 Mon Sep 17 00:00:00 2001 From: Young Joon Lee Date: Fri, 5 Apr 2024 16:34:52 +0900 Subject: [PATCH] refactor(user-management): improve user creation and ownership handling --- .copier-docker-config.yaml | 2 +- .docker/Dockerfile.ubuntu-20.04 | 29 ++++-- .docker/docker.common.env | 2 +- .../workflows/deploy-ubuntu-20.04-image.yaml | 1 + .github/workflows/release.yaml | 2 +- Makefile | 3 + README.md | 93 ++++++++++++++++++- 7 files changed, 119 insertions(+), 13 deletions(-) diff --git a/.copier-docker-config.yaml b/.copier-docker-config.yaml index 5d1b4ec..bc64973 100644 --- a/.copier-docker-config.yaml +++ b/.copier-docker-config.yaml @@ -1,5 +1,5 @@ # Changes here will be overwritten by Copier; do NOT edit manually -_commit: v0.29.0 +_commit: v0.29.5 _src_path: gh:entelecheia/hyperfast-docker-template app_dirname: entelecheia app_install_root: /opt diff --git a/.docker/Dockerfile.ubuntu-20.04 b/.docker/Dockerfile.ubuntu-20.04 index 57ab3cf..23c24c0 100644 --- a/.docker/Dockerfile.ubuntu-20.04 +++ b/.docker/Dockerfile.ubuntu-20.04 @@ -57,13 +57,21 @@ ENV USER_UID $ARG_USER_UID ENV USER_GID $ARG_USER_GID # Creates a non-root user with sudo privileges -RUN groupadd --gid $USER_GID $USERNAME \ - && adduser --uid $USER_UID --gid $USER_GID --force-badname --disabled-password --gecos "" $USERNAME \ - && echo "$USERNAME:$USERNAME" | chpasswd \ - && adduser $USERNAME sudo \ - && echo "$USERNAME ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers \ - && echo "$USERNAME ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/$USERNAME \ - && chmod 0440 /etc/sudoers.d/$USERNAME +# check if user exists and if not, create user +RUN if id -u $USERNAME >/dev/null 2>&1; then \ + # if the current user's user id is different from the specified user id, change the user id of the current user to the specified user id + if [ "$USER_UID" -ne "$(id -u $USERNAME)" ]; then \ + usermod --uid $USER_UID --gid $USER_GID $USERNAME; \ + fi; \ + else \ + groupadd --gid $USER_GID $USERNAME && \ + adduser --uid $USER_UID --gid $USER_GID --force-badname --disabled-password --gecos "" $USERNAME && \ + echo "$USERNAME:$USERNAME" | chpasswd && \ + adduser $USERNAME sudo && \ + echo "$USERNAME ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers && \ + echo "$USERNAME ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/$USERNAME && \ + chmod 0440 /etc/sudoers.d/$USERNAME; \ + fi # Fixes sudo error related to core dumps RUN echo "Set disable_coredump false" > /etc/sudo.conf @@ -93,8 +101,11 @@ USER $USERNAME RUN sh -c "$(wget -qO- https://dotfiles.entelecheia.ai/install)" USER root -RUN chown --recursive "${USER_UID}:${USER_GID}" "${WORKSPACE_ROOT}" -RUN chown --recursive "${USER_UID}:${USER_GID}" "${APP_INSTALL_ROOT}" +# if the user id is different from the specified user id, change the owner of the workspace to the specified user id +RUN if [ "$USER_UID" -ne "$(id -u $USERNAME)" ]; then \ + chown --recursive $USER_UID:$USER_UID $WORKSPACE_ROOT; \ + chown --recursive $USER_UID:$USER_UID $APP_INSTALL_ROOT; \ + fi USER $USERNAME # Specifies the command that will be executed when the container is run diff --git a/.docker/docker.common.env b/.docker/docker.common.env index 9b4d231..16fbb7e 100644 --- a/.docker/docker.common.env +++ b/.docker/docker.common.env @@ -33,7 +33,7 @@ DOCKER_PROJECT_ID=${DOCKER_PROJECT_ID:-"default"} DOCKER_USERNAME=${DOCKER_USERNAME:-"entelecheia"} # The username for Docker. IMAGE_VERSION=${IMAGE_VERSION:-"1.0.0"} # The version of the Docker image. If not set, "1.0.0" will be used. CONTAINER_REGISTRY=${CONTAINER_REGISTRY:-"ghcr.io"} # The Docker registry to push the image to. -CONTAINER_USERNAME=${USERNAME:-"app"} # The username of the user. If not set, the current user's username will be used. +CONTAINER_USERNAME="app" # The username of the user. If not set, the current user's username will be used. CONTAINER_USER_UID=${USER_UID:-"9001"} # The user ID in the Docker container. CONTAINER_USER_GID=${USER_GID:-"9001"} # The group ID in the Docker container. CONTAINER_GITHUB_USERNAME=${GITHUB_USERNAME:-"entelecheia"} # The GitHub username of the project diff --git a/.github/workflows/deploy-ubuntu-20.04-image.yaml b/.github/workflows/deploy-ubuntu-20.04-image.yaml index db461a4..453c071 100644 --- a/.github/workflows/deploy-ubuntu-20.04-image.yaml +++ b/.github/workflows/deploy-ubuntu-20.04-image.yaml @@ -66,6 +66,7 @@ jobs: type=raw,value=${{ env.IMAGE_VERSION }}-${{ env.IMAGE_VARIANT }} # set latest tag for docker branch type=raw,value=latest-${{ env.IMAGE_VARIANT }} + type=raw,value=latest # This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages. # It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see "[Usage](https://github.com/docker/build-push-action#usage)" in the README of the `docker/build-push-action` repository. diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 8b6e95e..a1c0393 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -30,7 +30,7 @@ jobs: steps: # Checkout the code base # - name: Checkout Code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 diff --git a/Makefile b/Makefile index c3439a5..923d4dd 100644 --- a/Makefile +++ b/Makefile @@ -84,6 +84,9 @@ init-project: initialize ## initialize the project (Warning: do this only once!) reinit-project: install-copier ## reinitialize the project (Warning: this may overwrite existing files!) @bash -c 'args=(); while IFS= read -r file; do args+=("--skip" "$$file"); done < .copierignore; copier copy "$${args[@]}" --answers-file .copier-docker-config.yaml --trust gh:entelecheia/hyperfast-docker-template .' +reinit-project-force: install-copier ## initialize the project ignoring existing files (Warning: this will overwrite existing files!) + @bash -c 'args=(); while IFS= read -r file; do args+=("--skip" "$$file"); done < .copierignore; copier copy "$${args[@]}" --answers-file .copier-docker-config.yaml --trust --force gh:entelecheia/hyperfast-docker-template .' + ##@ Docker symlink-global-docker-env: ## symlink global docker env file for local development diff --git a/README.md b/README.md index 7e7dc4c..4a7dc1f 100644 --- a/README.md +++ b/README.md @@ -1 +1,92 @@ -# dev-container \ No newline at end of file +# Development Containers + +[![version-image]][release-url] +[![release-date-image]][release-url] +[![license-image]][license-url] + +Development containers, or dev containers, are Docker containers that are specifically configured to provide a fully featured development environment. + +- GitHub: [https://github.com/entelecheia/dev-containers][repo-url] + +Development containers seek to find ways to develop, build, test, and deploy software in a containerized environment without the need to install any software on your local machine. + +## Prerequisites + +- Docker +- Docker Compose +- NVIDIA Docker (for GPU support, Optional) + +## Build and Run + +1. Build the Docker image: + + ```bash + make docker-build + ``` + + The `docker.ubuntu-20.04.env` file includes various configuration options and environment variables. The `docker-compose.ubuntu-20.04.yaml` file uses these variables to customize the behavior of the services. This is a common practice when you want to set different configurations for development, testing, and production environments. The `Dockerfile.ubuntu-20.04` file uses these variables to customize the Docker build. These files are automatically generated by Copier when you run the `copier copy` command. + +2. Start the Docker container: + + ```bash + make docker-up + ``` + + This will start a Docker container with the image built in the previous step. The container will run a bash lauch script that starts the application. + +## Usage + +After starting the container, you can access the application at `localhost:`. By default, the port is set to `19090`. + +You can also SSH into the container using the SSH port specified in `APP_HOST_SSH_PORT`. By default, the port is set to `2929`. + +## Volumes + +The `docker-compose.ubuntu-20.04.yaml` file specifies several volumes that bind mount directories on the host to directories in the container. These include the cache, the workspace directory, and the scripts directory. Changes made in these directories will persist across container restarts. + +## Troubleshooting + +If you encounter any issues with this setup, please check the following: + +- Make sure Docker and Docker Compose are installed correctly. +- Make sure NVIDIA Docker is installed if you're planning to use GPU acceleration. +- Ensure the environment variables in the `docker.ubuntu-20.04.env` file are correctly set. +- Check the Docker and Docker Compose logs for any error messages. + +## Environment Variables + +In Docker, environment variables can be used in the `docker-compose.ubuntu-20.04.yaml` file to customize the behavior of the services. + +The `docker-compose` command has an `--env-file` argument, but it's used to set the environment variables for the services defined in the `docker-compose.yaml` file, not for the `docker-compose` command itself. The variables defined in the `--env-file` will not be substituted into the `docker-compose.yaml` file. + +However, the environment variables we set in the `.docker/docker.ubuntu-20.04.env` file are used in the `docker-compose.app.yaml` file. For example, the `$BUILD_FROM` variable is used to set the base image for the Docker build. Therefore, we need to export these variables to the shell environment before running the `docker-compose` command. + +This method also allows us to use shell commands in the variable definitions, like `"$(whoami)"` for the `USERNAME` variable, which wouldn't be possible if we used the `--env-file` argument. Shell commands in the `.env` file are not evaluated. + +### Files for Environment Variables + +- `.docker/docker.common.env`: Common environment variables for all Docker images. +- `.docker/docker.ubuntu-20.04.env`: Environment variables for the Docker image. +- `.env.secret`: Secret environment variables that are not committed to the repository. + +## Changelog + +See the [CHANGELOG] for more information. + +## Contributing + +Contributions are welcome! Please see the [contributing guidelines] for more information. + +## License + +This project is released under the [MIT License][license-url]. + +[license-image]: https://img.shields.io/github/license/entelecheia/dev-containers +[license-url]: https://github.com/entelecheia/dev-containers/blob/main/LICENSE +[version-image]: https://img.shields.io/github/v/release/entelecheia/dev-containers?sort=semver +[release-date-image]: https://img.shields.io/github/release-date/entelecheia/dev-containers +[release-url]: https://github.com/entelecheia/dev-containers/releases +[repo-url]: https://github.com/entelecheia/dev-containers +[changelog]: https://github.com/entelecheia/dev-containers/blob/main/CHANGELOG.md +[contributing guidelines]: https://github.com/entelecheia/dev-containers/blob/main/CONTRIBUTING.md +