Search code examples
dockergodocker-engine

Unable to mount a folder in Docker from container with Go Docker Engine API


I am trying to run docker inside container using Go Docker Engine API. I am able to mount a folder from host system to the container but only empty dir is being copied into the docker inside the container. Please help me out if there is any alternative for the same. I am starting my container using following command.

docker run --rm -v C:\Users\user\source\repos\game:/app/myrepo -v /var/run/docker.sock:/var/run/docker.sock testimage

Attached is the piece of code. Go Docker SDK code to start container

resp, err := cli.ContainerCreate(ctx, &container.Config{
    Image: "hello-image",
    Cmd:   []string{"ls"}, #the actual cmd would look different
    Tty:   true,
}, &container.HostConfig{
    Binds: []string{
        "/app/myrepo:/myrepo",
    },
}, nil, nil, containername)
if err != nil {
    panic(err)
}

updated Code for binds with absolute path

resp, err := cli.ContainerCreate(ctx, &container.Config{
    Image: "hello-image",
    Cmd:   []string{"ls"}, #the actual cmd would look different
    Tty:   true,
}, &container.HostConfig{
    Mounts: []mount.Mount{
        {
            Type:   mount.TypeBind,
            Source: "/app/myrepo",
            Target: "/myrepo",
        },
    },
}, nil, nil, containername)
if err != nil {
    panic(err)
}

Solution

  • As discussed in the comments the OP is running an app in a container. The app is connecting to the docker daemon on the host (via shared /var/run/docker.sock) and attempting to create a container. The issue was that the request includes a mount point, the source being /app/myrepo, which a source path that is valid within the container but not on the host.

    To aid in understanding why this is an issue you need to consider how the API request is made. Your code will generate a JSON formatted request; this will include something like this:

    ...
    "HostConfig": {
       ...
       "Mounts": [
           {
               "Source": "/app/myrepo",
               "Destination": "/myrepo",        
           }
       ]
    }
    

    It's important to note that the Source path is passed as a string and the Docker Daemon will interpret this in the hosts (e.g. the windows box) context. When it attempts to locate the requested path (/app/myrepo) it will not find it because that path does not exist on the host. To correct this you need to send a valid path e.g.

    Mounts: []mount.Mount{
       {
          Type:   mount.TypeBind,
          Source: "c:/Users/user/source/repos/game",
          Target: "/myrepo",
        },
    }
    

    One note of caution; accessing the Docker API in this way (bind mount /var/run/docker.sock:) is convenient but if someone gains access to the container then they also gain full control of all containers (because they can access the Docker API). You may want to consider using a proxy (for example).