Search code examples
dockerjenkinsdocker-composecontainersdocker-desktop

I can access docker.sock in Ubuntu, but not in Docker Desktop Windows


I want to set up CICD with docker and Jenkins on Windows with Docker Desktop and run docker commands from the Jenkins container. As I understand it, one way to do that is to expose the hosts docker daemon through the socket docker.sock to the Jenkins container. When I run the below compose.yaml

version: '3.8'
services:
    jenkins:
      image: jenkins/jenkins:lts
      privileged: true
      user: root
      ports:
        - 8080:8080
        - 50000:50000
      volumes:
        - jenkins-data:/var/jenkins_home
        - /var/run/docker.sock:/var/run/docker.sock
        - /usr/bin/docker:/usr/bin/docker

volumes:
  jenkins-data:

with the command docker compose up -d --build in an Ubuntu VM with docker installed, the Jenkins container can run docker commands and everything seems to be working as intended. E.g. I can run docker -v inside the docker container (no sudo is needed).

But when I run the same compose.yaml on my Windows (Windows 10 Pro, 19045.3693) laptop with Docker Desktop (4.25.2), the Jenkins container can’t run docker commands. When I run docker -v inside the Jenkins container I get the error:

/bin/sh: 1: docker: not found

I have also installed sudo in the Jenkins VM and run sudo docker -v and get the error:

sudo: docker: command not found

More things I have tried is to use an extra slash - //var/run/docker.sock:/var/run/docker.sock. I have tried using named pipes but I think that is only relevant if you want to run a Windows container. I have tried to also bind mount /usr/bin/docker:/usr/bin/docker, //usr/bin/docker:/usr/bin/docker and /usr/local/bin/docker:/usr/bin/docker.

Any ideas?

Edit: I forgot - /usr/bin/docker:/usr/bin/docker under volumes. This is needed for it to work in Ubuntu.

Edit: This post is about how to get it to work with Docker Desktop on Windows. All other posts doesn't mention Docker Desktop and seem to assume a Linux environment. Added clarification in first sentence. I don't think this question should be closed as it can illustrate the differences between e.g. Ubuntu VM and Docker Desktop.


Solution

  • The current jenkins/jenkins:lts image does not have docker client installed, you need to add it to an image and use it.

    Interesting how and why your compose file works on ubuntu VM even though no docker cli installed in the container running from jenkins/jenkins:lts. Maybe previous jenkins/jenkins:lts image had it, and your docker engine on the ubuntu VM still has it and that is what used in your VM? This is why you should never use latest, lts, etc running tags/versions because the underlying software can and will change over time, you should pin your version like jenkins/jenkis:1.2.3-debian or something like this.

    Anyways, this works on my Windows 10 machine with Docker Desktop for Windows:

    Create this Dockerfile:

    FROM jenkins/jenkins:2.426.1-lts-jdk17
    
    USER root
    
    # Install Docker client cli
    RUN apt-get update && \
        apt-get -y install \
        apt-transport-https \
        ca-certificates \
        curl \
        gnupg2 \
        software-properties-common && \
        curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add - && \
        apt-key fingerprint 0EBFCD88 && \
        add-apt-repository \
        "deb [arch=amd64] https://download.docker.com/linux/debian \
        $(lsb_release -cs) \
        stable" && \
        apt-get update && \
        apt-get -y install docker-ce-cli
    
    # create docker group 
    RUN groupadd -g 1001 docker
    
    # add jenkins user to docker group
    RUN usermod -aG docker jenkins
    
    USER jenkins
    

    !!!Important!!! You must use the same GUID for docker group in RUN groupadd -g 1001 docker command as it is on the wsl distro that you enabled the Docker Desktop WSL2 integration with and from where you issue your commands (docker build, docker run, etc). You can check the GUID on the wsl2 distro with getent group docker, for me it is 1001.

    Note: Docker engine, the server, itself is not running in this wsl2 distro but rather it has it's own separate wsl2 distros with names docker-desktop and docker-desktop-data. You connect to this docker engine server with the docker client, the docker cli command.

    Build the image: docker build -f Dockerfile -t myjenkins:1.0.0-docker-cli .

    Run the container from the image from the wsl2 distro shell that you enabled Docker Desktop integration with: docker run -v /var/run/docker.sock:/var/run/docker.sock --rm -it myjenkins:1.0.0.-docker-cli sh

    Execute docker ps in the container shell and you will see your containers running on the host, including the container that you are currently inside.

    Be aware that granting this kind of access to the container gives the jenkins user root level access on the host: https://docs.docker.com/engine/security/#docker-daemon-attack-surface