Docker CIFS – How to Mount CIFS as a Docker Volume


Docker CIFS Samba

Overview

In my environment I’m using a drobo CIFS NAS storage device. Data on the NAS is exported over CIFS to various servers. I have a few docker containers that need read/write access to the data stored on CIFS. However, when attempting to use the docker -v option to bind mount the cifs share into the docker container I ran into “permission denied” issues caused by SELinux and the CIFS mount UID/GID mapping. Here’s how I solved them.

In this article we will

  • Mount a CIFS share on the host OS with the appropriate SELinux context and UID/GID mapping for Docker.
  • Create a Docker container that uses our CIFS share as a data volume with read/write access.
  • SELinux Configuration

    The docker container will not be permitted to access your CIFS mount point unless you or mount the share with the appropriate SELinux security context.

    The context used to make this work on my CentOS 7 host is:

    context=system_u:object_r:svirt_sandbox_file_t:s0

    Here’s an example of the fstab entry to mount the CIFS share on /mnt/cifs_share:

     
    #/etc/fstab
     
    //10.0.0.200/cifs_share        /mnt/cifs_share cifs    defaults,username=USER,password=PASS,context=system_u:object_r:svirt_sandbox_file_t:s0      0 0

    Mapping Local User Permissions to CIFS Share Permissions

    Unlike NFS, a CIFS mount handles user authentication at mount time. This means that all files and directories at our CIFS mount point will be owned by the same user/group. This may be a problem if the user of the process running in your container and the user of the CIFS mount are not the same. I worked around this by mounting the same CIFS share multiple times with different uid and gid arguments.

    To mount a CIFS share as a particular user use the uid, gid, forceuid and forcegid mount.cifs options.

    # from 'man mount.cifs'
    uid=arg - sets the uid that will own all files or directories on the mounted filesystem when the server does not provide ownership information. It may be specified as either a username or a numeric uid. When not specified, the default is uid 0. The mount.cifs helper must be at version 1.10 or higher to support specifying the uid in non-numeric form. See the section on FILE AND DIRECTORY OWNERSHIP AND PERMISSIONS below for more information.
     
    forceuid -instructs the client to ignore any uid provided by the server for files and directories and to always assign the owner to be the value of the uid= option.
     
    gid=arg - sets the gid that will own all files or directories on the mounted filesystem when the server does not provide ownership information. It may be specified as either a groupname or a numeric gid. When not specified, the default is gid 0. The mount.cifs helper must be at version 1.10 or higher to support specifying the gid in non-numeric form.
     
    forcegid - instructs the client to ignore any gid provided by the server for files and directories and to always assign the owner to be the value of the gid= option.

    (source: http://linux.die.net/man/8/mount.cifs)

    Here’s an example FSTAB entry to mount CIFS share as local user “nobody” at path /mnt/cifs_share-nobody

    #/etc/fstab
     
    #mount CIFS share as local user "nobody" at path /mnt/cifs_share-nobody
     
    //10.0.0.200/cifs_share        /mnt/cifs_share-nobody cifs  username=USER,password=PASS,uid=nobody,forceuid,gid=nobody,forcegid,context=system_u:object_r:svirt_sandbox_file_t:s0

    Creating the Docker CIFS enabled container

    Now that we have the CIFS share mounted as the appropriate user with the necessary SELinux context on the host OS we can use it in our Docker container as a data volume with the “docker run -v” option.

    #from 'man docker-run'
     
                  -v, --volume=volume[:ro|:rw]
                     Bind mount a volume to the container.
     
                  The -v option can be used one or more times to add one or more mounts to a container. These mounts can then be used in other containers using the --volumes-from option.
     
                  The  volume  may be optionally suffixed with :ro or :rw to mount the volumes in read-only or read-write mode, respectively. By default, the volumes are mounted read-write.
                  See examples.

    Source https://docs.docker.com/reference/run/#volume-shared-filesystems

    Now, let’s mount our “nobody” CIFS share as /data in an example ubuntu Docker container that runs bash.

    docker run -it -v /mnt/cifs_share-nobody:/data 
     
    # Create a test file from the Host OS
    [root@dockerbox ~]# touch /mnt/cifs_share-nobody/testfile
     
    # Run an ubuntu:trusty container mounting our CIFS volume as /data inside
    [root@dockerbox ~]# docker run -it -v /mnt/cifs_share-nobody:/data ubuntu:trusty /bin/bash
     
    # Access our CIFS share from inside the container
    root@c90e78c4f38e:/# ls /data
    testfile

    And there you have it. Access to a CIFS share from inside a Docker container.

    More about CIFS Permissions from the mount.cifs man page:

    File And Directory Ownership And Permissions
     
    The core CIFS protocol does not provide unix ownership information or mode for files and directories. Because of this, files and directories will generally appear to be owned by whatever values the uid= or gid= options are set, and will have permissions set to the default file_mode and dir_mode for the mount. Attempting to change these values via chmod/chown will return success but have no effect.
     
    When the client and server negotiate unix extensions, files and directories will be assigned the uid, gid, and mode provided by the server. Because CIFS mounts are generally single-user, and the same credentials are used no matter what user accesses the mount, newly created files and directories will generally be given ownership corresponding to whatever credentials were used to mount the share.
     
    If the uid's and gid's being used do not match on the client and server, the forceuid and forcegid options may be helpful. Note however, that there is no corresponding option to override the mode. Permissions assigned to a file when forceuid or forcegid are in effect may not reflect the the real permissions.
     
    When unix extensions are not negotiated, it's also possible to emulate them locally on the server using the "dynperm" mount option. When this mount option is in effect, newly created files and directories will receive what appear to be proper permissions. These permissions are not stored on the server however and can disappear at any time in the future (subject to the whims of the kernel flushing out the inode cache). In general, this mount option is discouraged.
     
    It's also possible to override permission checking on the client altogether via the noperm option. Server-side permission checks cannot be overriden. The permission checks done by the server will always correspond to the credentials used to mount the share, and not necessarily to the user who is accessing the share.

    8 Responses to “Docker CIFS – How to Mount CIFS as a Docker Volume”

    1. trey Says:

      this absolutely did not work for me at all

      the remote mounted folders, when viewed in the docker container, were always empty. Any files created would only show up on the host, if the folder was umounted first.

      super frustrated,
      -trey

      [Reply]

      Brett Reply:

      I’m seeing the same issue. My folder is always empty.
      @trey, did you figure anything out? It is super frustrating indeed.

      [Reply]

      Keith Reply:

      What does your config look like?

      [Reply]

    2. Trey Says:

      @Brett there is a bug that the docker service has to be started after the remote filesystems have been mounted. I bounced docker and then altered my systemd config files for docker as I described here: https://github.com/docker/docker/issues/4213#issuecomment-72400946 and it’s been working great for me since.

      [Reply]

    3. Andra Says:

      la verdad es que sed, trato de tener las me1quinas de lrbroatoaio lo me1s actualizadas posible (sin miedo ). Aunque es cierto que en produccif3n hay muchos dinosaurios tirando de smbfs.Actualmente monto con CIFS una particif3n Windows compartida con Vista SP1 en una Kubuntu 8.10 Intrepid.

      [Reply]

    4. jojo Says:

      once volume is mounted, all file have the same ACL permission, and not able to alter. do you have the same issue?

      [Reply]

      Keith Reply:

      Yes. I use a different mount point for each application to separate privileges.

      [Reply]

      jojo Reply:

      i have two volume, one is default permission 755 and another one i specify 600. but when i use “-v” to mount these two volume into a docker container 755->/home, 600->/readonly. permision under 600 are all question mark. do you have the same issue?

      [Reply]

    Join the Conversation