Here in this post, I’m going to talk about something that isn’t part of the laboratory, but helps me on several occasions. Create a shared folder/volume, I always need to copy or read files between VMs, Dockers and hosts, be it the VM hosts or my workstation.
I don’t want to install directly on the host. So I could create a VM for this, install Samba and have more control, but now, I prefer to create a Docker Container and I won’t integrate with LDAP or worry about security, etc. It’s just to make file transfers easier for me, if it were something really linked to the project, yes, there would be a little more work on the subject.

To do this, I will use Samba and an image that already has a long history of use, is well assembled (for what I need) and stable: https://github.com/crazy-max/docker-samba

Preparation.

I will create a simple structure on the VMs/Dockers host, a /work/samba folder (work is my work root folder).
Inside Samba, I create docker-compose.yaml and two important folders:

  • smb – It will have the configurations and files that samba creates during use.
  • work – This will be the rais folder of my share.
mkdir -p /work/samba/smb
mkdir -p /work/samba/work


samba
├── docker-compose.yaml
├── smb
│   └── config.yaml
└── work

Also, I will create a user devopsdbshare in Linux with the password 1234qwer. But removing permission to log in to Bash is not necessary and is safer.

groupadd -g 1003 devopsdbshare
useradd devopsdbshare -u 1003 -g 1003 -m -s /bin/bash

sudo smbpasswd -a devopsdbshare
sudo smbpasswd -e devopsdbshare

After creating, look for the user information, in fact, the uid and gid will be important in the configuration below.

cat /etc/passwd | grep devopsdbshare

devopsdbshare:x:1003:1003:,,,:/home/devopsdbshare:/bin/bash

With the folders and the user created, I will assign the folder to the user devopsdbshare:

sudo chown devopsdbshare:devopsdbshare /work/samba/work

Configuration.

The configuration file (config.yaml) described below needs to be located in the folder that will be converted to /data in the Docker container, so as you will see below in docker compose: /work/samba/smb/config.yaml

auth:
  - user: devopsdbshare
    group: devopsdbshare
    uid: 1003
    gid: 1003
    password: 1234qwer

global:
  - "hosts allow = 127.0.0.0/8 172.21.5.0/24"
  - "hosts deny = '0.0.0.0/0'"
  - "force user = devopsdbshare"
  - "force group = devopsdbshare"  

share:
  - name: work
    path: /work
    browsable: yes
    readonly: no
    guestok: no
    validusers: devopsdbshare
    writelist: devopsdbshare
    veto: no

There are many other configurations, which you can find in the Samba manual pages. Here, I will leave some considerations of this configuration.

As I said, I’m not going to worry about security at this point, so the auth section is the simplest possible, I’m not going to create integration with LDAP for this now, but I also don’t want to use my user. That’s why the devopsdbshare user is configured and has a password in plain text.
hosts allow – I will limit it only to localhost and the network I am using in this lab.
deny hosts – all origins other than the ones above.
name – is the name of the share, which will be used when we mount the other VMs/Hosts.
path – is the path that will be shared, this path must be mounted in the Container/Docker, more below see in docker-compose.
The rest are simple settings, I will not accept GuestUsers, the content can be browsed, it is not read only, and only applies to the devopsdbshare user.

File created and copied to the folder described above, let’s take care of docker compose.

The file is created in /work/samba/docker-compose.yaml

version: "3.5"

services:
  samba:
    image: crazymax/samba
    container_name: srv-fileserver-01
    network_mode: host
    volumes:
      - ./smb:/data
      - ./work:/work
    environment:
      - "TZ=$TIMEZONE"
      - "SAMBA_LOG_LEVEL=3"
      - "CONFIG_FILE=/data/config.yaml"
    restart: always

The environment variable SAMBA_LOG_LEVEL = 3 is for debugging, only for Info the ideal is to leave it at 0.

Note that the volumes mounted in the container are the ones I mentioned and created above, the share folder and the configuration folder.

Another point, for simple convenience, I added the CONFIG_FILE environment variable, to change the file name to config.yaml. But it’s worth showing that you can leave the file in any other folder and name.

Now that the configuration is ready and compose is ready, let’s create the container:

docker compose up -d

Check:

docker container ls

CONTAINER ID   IMAGE                 COMMAND                  CREATED          STATUS                    PORTS                                                                                  NAMES
d70c9407fbaa   crazymax/samba        "/init"                  57 minutes ago   Up 57 minutes (healthy)                                                                                          srv-fileserver-01

To follow the logs:

docker container logs srv-fileserver-01 --follow

If everything went well, you now have a Samba server ready with a share called work.

Mount on a Linux host.

First, create the folder where the mount will be done.

mkdir /mnt/work
apt install -y cifs-utils

To avoid exposing the username and password, we will create a secrets file in /root, so that only root has access:

mkdir /root/secrets
vi /root/secrets/secrets

username=devopsdbshare
password=1234qwer

Now, there are two ways to mount, the first is temporary, any reset on the host or even after the section is finished, the mount will be deactivated. This solution is great for temporary use.

You just need to run the mount command with the share parameters and the path will be ready to use.

sudo mount -t cifs -o credentials=/root/secrets/secrets,iocharset=utf8,file_mode=0777,dir_mode=0777 //172.21.5.76/work /mnt/work

Or if you want the solution where the share is fixed, change the /etc/fstab file and add the line below:

vi /etc/fstab

//172.21.5.76/work /mnt/work cifs credentials=/root/secrets/secrets,iocharset=utf8,file_mode=0777,dir_mode=0777 0 0

After changing the fstab file, you need to mount or restart the host.

mount -a

After this, use is normal, like any folder and at the same time, on other hosts, sharing files, etc.

If you want to remove the mount, just remove the entry from the /etc/fstab file and, in either case, to remove the share from the host, just run umount.

umount /mnt/work/

Mount on a Docker Container.

There are several possibilities for how to mount an SMB share in a container, create a new image, mount the share on the host and map it to the container, even overriding CMD or Entrypoint with mount scripts.
I prefer to create a docker volume with share and then use this volume in the containers I need, I think this process is cleaner.
Below I describe how to do it.

First, create the volume with your Share information, I will name this volume devopsdb-share.
The opt device parameter is the full path of share, server + share.
The opt parameter is practically the same string as mount in Linux, but the addr option is really just the server, in my case IP 172.21.5.72, I could have created a DNS for this.

docker volume create \
        --driver local \
        --opt type=cifs \
        --opt device=//172.21.5.72/work \
        --opt o=addr=172.21.5.72,username=devopsdbshare,password=1234qwer,iocharset=utf8,file_mode=0777,dir_mode=0777  \
        --name devopsdb-share

Validate the volume:

$ docker volume ls

DRIVER    VOLUME NAME
local     devopsdb-share

#######################################################################################################################

$ docker volume inspect devopsdb-share

[
    {
        "CreatedAt": "2024-04-17T22:12:06+01:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/devopsdb-share/_data",
        "Name": "devopsdb-share",
        "Options": {
            "device": "//172.21.5.72/work",
            "o": "addr=172.21.5.72,username=devopsdbshare,password=1234qwer,iocharset=utf8,file_mode=0777,dir_mode=0777",
            "type": "cifs"
        },
        "Scope": "local"
    }
]

Then create the container and use the volume created above.

docker run -tid \
    --network local-bridge \
    --platform linux/amd64 \
    -v devopsdb-share:/work \
    --name test-smb-share ubuntu:22.04

Enter the container’s bash and check the mapping:

$ docker exec -it -u root --privileged test-smb-share /bin/bash

root@cc54cf628ae9:/# cd /work/

root@cc54cf628ae9:/work# ll
total 4
drwxrwxrwx 2 root root    0 Apr 17 11:08 ./
drwxr-xr-x 3 root root 4096 Apr 17 11:16 ../
drwxrwxrwx 2 root root    0 Apr 17 11:08 bind9/

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.