├── .github └── workflows │ └── docker-image.yml ├── Dockerfile ├── Makefile ├── README.md ├── entrypoint.sh ├── k8s-deployment.yml └── supervisor └── dockerd.conf /.github/workflows/docker-image.yml: -------------------------------------------------------------------------------- 1 | name: Build and Push Docker Image 2 | 3 | on: 4 | push: 5 | 6 | env: 7 | REGISTRY: ghcr.io 8 | IMAGE_NAME: ${{ github.repository }} 9 | IMAGE_TAG: latest 10 | 11 | jobs: 12 | build_and_push: 13 | runs-on: ubuntu-latest 14 | permissions: 15 | contents: read 16 | packages: write 17 | 18 | steps: 19 | - name: Log in to Docker Hub 20 | uses: docker/login-action@v3 21 | with: 22 | username: ${{ vars.DOCKER_USER }} 23 | password: ${{ secrets.DOCKER_PAT }} 24 | 25 | - name: Log into ${{ env.REGISTRY }} 26 | uses: docker/login-action@v3 27 | with: 28 | registry: ${{ env.REGISTRY }} 29 | username: ${{ github.actor }} 30 | password: ${{ secrets.GITHUB_TOKEN }} 31 | 32 | - name: Checkout 33 | uses: actions/checkout@v4 34 | 35 | - name: Set up Docker Buildx 36 | uses: docker/setup-buildx-action@v3 37 | with: 38 | version: "lab:latest" 39 | driver: cloud 40 | endpoint: "${{ vars.DOCKER_ORG }}/cloud-builder" 41 | install: true 42 | 43 | - name: Build and push Docker image 44 | uses: docker/build-push-action@v6 45 | with: 46 | context: . 47 | push: true 48 | platforms: linux/amd64,linux/arm64 49 | tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }} 50 | outputs: ${{ github.event_name == 'pull_request' && 'type=cacheonly' || 'type=registry' }} 51 | 52 | - name: Image pushed successfully 53 | run: echo "Docker image ${{ env.IMAGE_NAME }} pushed successfully to ${{ env.REGISTRY }}. Use 'docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }}' to pull the image." 54 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Use Ubuntu 24.10 as the base image 2 | 3 | FROM ubuntu:24.10 4 | 5 | # Install necessary packages 6 | RUN apt-get update \ 7 | && apt-get install -y --no-install-recommends \ 8 | ca-certificates \ 9 | curl \ 10 | gnupg \ 11 | iptables \ 12 | supervisor 13 | 14 | # Install Docker using a script from Docker's official website 15 | RUN curl -fsSL https://get.docker.com | sh 16 | 17 | # Install NVIDIA Container Toolkit for GPU support 18 | RUN curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \ 19 | && curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \ 20 | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \ 21 | tee /etc/apt/sources.list.d/nvidia-container-toolkit.list \ 22 | && apt-get update \ 23 | && apt-get install -y nvidia-container-toolkit \ 24 | && nvidia-ctk runtime configure --runtime=docker \ 25 | && apt-get clean \ 26 | && rm -rf /var/lib/apt/lists/* 27 | 28 | # Copy entrypoint script and Supervisor configuration files into the container 29 | COPY entrypoint.sh /usr/local/bin/ 30 | COPY supervisor/ /etc/supervisor/conf.d/ 31 | 32 | # Make entrypoint script executable 33 | RUN chmod +x /usr/local/bin/entrypoint.sh 34 | 35 | # Create a volume for Docker's data directory 36 | VOLUME /var/lib/docker 37 | 38 | # Define the entrypoint for the container 39 | ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] 40 | 41 | # Default command to run if no other command is specified 42 | CMD ["bash"] 43 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | IMAGE_NAME = dind-ubuntu-nvidia 2 | TAG ?= latest 3 | REGISTRY_PREFIX ?= docker.io/prasadb89 4 | PLATFORM ?= linux/amd64,linux/arm64 5 | 6 | GPU_COUNT ?= all 7 | 8 | build: 9 | @echo "Building Docker image..." 10 | @echo "Image Name: ${IMAGE_NAME}" 11 | @echo "Tag: ${TAG}" 12 | @echo "Registry Prefix: ${REGISTRY_PREFIX}" 13 | @echo "Platform: ${PLATFORM}" 14 | @docker buildx build --push -f Dockerfile -t ${REGISTRY_PREFIX}/${IMAGE_NAME}:${TAG} --platform ${PLATFORM} . 15 | 16 | run_standard: 17 | @echo "Running standard Docker container..." 18 | @echo "Image: ${REGISTRY_PREFIX}/${IMAGE_NAME}:${TAG}" 19 | @docker run -it --rm --privileged ${REGISTRY_PREFIX}/${IMAGE_NAME}:${TAG} 20 | 21 | run_gpu: 22 | @echo "Running Docker container with GPU..." 23 | @echo "Image: ${REGISTRY_PREFIX}/${IMAGE_NAME}:${TAG}" 24 | @echo "GPU Count: ${GPU_COUNT}" 25 | @docker run -it --rm --privileged --gpus ${GPU_COUNT} ${REGISTRY_PREFIX}/${IMAGE_NAME}:${TAG} 26 | 27 | pull: 28 | @echo "Pulling Docker image..." 29 | @echo "Image: ${REGISTRY_PREFIX}/${IMAGE_NAME}:${TAG}" 30 | @docker pull ${REGISTRY_PREFIX}/${IMAGE_NAME}:${TAG} 31 | 32 | push: 33 | @echo "Pushing Docker image..." 34 | @echo "Image: ${REGISTRY_PREFIX}/${IMAGE_NAME}:${TAG}" 35 | @docker push ${REGISTRY_PREFIX}/${IMAGE_NAME}:${TAG} 36 | 37 | build_run_standard: build run_standard 38 | 39 | build_run_gpu: build run_gpu 40 | 41 | build_push: build push 42 | 43 | k8s_deploy: 44 | @echo "Deploying to Kubernetes..." 45 | @kubectl apply -f k8s-deployment.yml 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ubuntu-based Docker-in-Docker (DinD) Environment with NVIDIA Container Runtime Support 2 | 3 | ## Overview 4 | This repository offers an Ubuntu-based Docker-in-Docker (DinD) environment tailored for containerized development, enriched with NVIDIA container runtime support. The base image is crafted on Ubuntu 24.10. 5 | 6 | ## Features 7 | - **Ubuntu 24.10**: Built on the latest stable Ubuntu LTS platform for reliability and long-term support. 8 | - **Docker-in-Docker (DinD)**: Enables nested Docker containerization, ideal for CI/CD pipelines and advanced development workflows. 9 | - **NVIDIA Container Runtime**: Facilitates execution of GPU-accelerated applications leveraging NVIDIA GPUs for enhanced performance. 10 | 11 | ## Usage 12 | 13 | ### Pull the Image 14 | To obtain the pre-built Docker image from Docker Hub, execute the following command: 15 | 16 | ```sh 17 | docker pull ghcr.io/prasad89/dind-ubuntu-nvidia 18 | ``` 19 | 20 | ### Run the Container 21 | 22 | #### Standard (Non-GPU) Usage 23 | For standard Docker operations without GPU support: 24 | 25 | ```sh 26 | docker run -it --rm --privileged ghcr.io/prasad89/dind-ubuntu-nvidia 27 | ``` 28 | 29 | #### GPU-Accelerated Usage 30 | To utilize NVIDIA GPU support within the Docker environment: 31 | 32 | ```sh 33 | docker run -it --rm --privileged --gpus all ghcr.io/prasad89/dind-ubuntu-nvidia 34 | ``` 35 | 36 | Replace `--gpus all` with specific GPU settings (`--gpus device=0,1`) as per your hardware configuration. 37 | 38 | #### Deploying in Kubernetes 39 | To deploy the container in a Kubernetes cluster: 40 | 41 | ```sh 42 | kubectl apply -f https://raw.githubusercontent.com/prasad89/dind-ubuntu-nvidia/main/k8s-deployement.yml 43 | ``` 44 | 45 | ### Using the Makefile 46 | 47 | This repository includes a Makefile to simplify building, running, pulling, and pushing the Docker image. Below are the available commands: 48 | 49 | #### Build the Docker Image 50 | ```sh 51 | make build 52 | ``` 53 | 54 | By default, this `make` command builds a multiple architecture image using `buildx`. Make sure you have a compatible `buildx` driver installed to run this. 55 | 56 | Optionally, if you don't want to build for multiple architectures, you can simply run: `docker build -f Dockerfile -t REGISTRY_PREFIX/IMAGE_NAME:TAG .` 57 | 58 | #### Run the Container in Standard Mode (without GPU) 59 | ```sh 60 | make run_standard 61 | ``` 62 | 63 | #### Run the Container with GPU Support 64 | ```sh 65 | make run_gpu 66 | ``` 67 | 68 | #### Pull the Docker Image from the Registry 69 | ```sh 70 | make pull 71 | ``` 72 | 73 | #### Push the Docker Image to the Registry 74 | ```sh 75 | make push 76 | ``` 77 | 78 | #### Build and Run the Docker Image in Standard Mode 79 | ```sh 80 | make build_run_standard 81 | ``` 82 | 83 | #### Build and Run the Docker Image with GPU Support 84 | ```sh 85 | make build_run_gpu 86 | ``` 87 | 88 | #### Build and Push the Docker Image to the Registry 89 | ```sh 90 | make build_push 91 | ``` 92 | 93 | #### Deploy the Container in Kubernetes 94 | ```sh 95 | make k8s_deploy 96 | ``` 97 | 98 | ### Customizing the Makefile 99 | 100 | If you need to customize the image name, tag, or registry prefix, you can modify the variables in the Makefile: 101 | 102 | - **IMAGE_NAME**: The name of the Docker image (default: `dind-ubuntu-nvidia`). 103 | - **TAG**: The tag for the Docker image (default: `latest`). 104 | - **REGISTRY_PREFIX**: The registry prefix where the image is stored (default: `ghcr.io/prasad89`). 105 | - **GPU_COUNT**: The number of GPUs to use (default: `all`). Adjust this as needed for your specific setup. 106 | - **PLATFORM**: The platforms for which the Docker image is built (default: `linux/amd64,linux/arm64`). -------------------------------------------------------------------------------- /entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Function to wait for a process to start 4 | function wait_for_process() { 5 | local max_time_wait=30 6 | local process_name="$1" 7 | local waited_sec=0 8 | while ! pgrep "$process_name" >/dev/null && ((waited_sec < max_time_wait)); do 9 | echo "Process $process_name is not running yet. Retrying in 1 second" 10 | echo "Waited $waited_sec seconds of $max_time_wait seconds" 11 | sleep 1 12 | ((waited_sec++)) 13 | if ((waited_sec >= max_time_wait)); then 14 | return 1 15 | fi 16 | done 17 | return 0 18 | } 19 | 20 | echo "Starting supervisor" 21 | supervisord -n >> /dev/null 2>&1 & 22 | 23 | echo "Waiting for dockerd to be running" 24 | wait_for_process dockerd 25 | if [ $? -ne 0 ]; then 26 | echo "Error: dockerd is not running after max time" 27 | exit 1 28 | else 29 | echo "dockerd is running" 30 | fi 31 | 32 | # Execute specified command 33 | exec "$@" 34 | -------------------------------------------------------------------------------- /k8s-deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: dind-ubuntu-nvidia 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | app: dind-ubuntu-nvidia 10 | template: 11 | metadata: 12 | labels: 13 | app: dind-ubuntu-nvidia 14 | spec: 15 | containers: 16 | - name: dind-ubuntu-nvidia 17 | image: ghcr.io/prasad89/dind-ubuntu-nvidia 18 | stdin: true 19 | securityContext: 20 | privileged: true 21 | resources: 22 | requests: 23 | memory: 100Mi 24 | cpu: 100m 25 | limits: 26 | nvidia.com/gpu: 1 27 | volumeMounts: 28 | - name: docker 29 | mountPath: /var/lib/docker 30 | volumes: 31 | - name: docker 32 | emptyDir: {} 33 | -------------------------------------------------------------------------------- /supervisor/dockerd.conf: -------------------------------------------------------------------------------- 1 | [program:dockerd] 2 | command=/usr/bin/dockerd 3 | autostart=true 4 | autorestart=true 5 | stderr_logfile=/var/log/dockerd.err.log 6 | stdout_logfile=/var/log/dockerd.out.log --------------------------------------------------------------------------------