Set Up Samba Server in Docker
!IMPORTANT: Permission setting is very annoying but critical, sometimes you need take long time to fine tune it and debug.
!IMPORTANT: When setting up a Samba server in Docker in OSX, you will encounter problems such as Operation not suppored
when using bind mount
. Roughly saying, the reason is Docker run in a light VM in Mac and your Mac host uses a different file system(HFS+) compared to Linux(ext4 or similar). So switching to volume mount
will solve this potential problem.
Some takeaways about Permission:
- Creating and deleting files is controlled by permissions on the directory.
- Modifying the file is controlled by permissions on the file. You may have a mask which is removing the write privilege from the file.
When I turned to set up Samba server locally, the main purpose is that I would like to integrate the Samba server into my Docker Compose project to mock a real remote Samba server, which will facilitate your local development in Docker environment.
So this blog will illustrate to set up a Samba server and a client, and test interaction between them.
Start Samba Server in Docker
Here, we use Samba server image from dperson/samba. Although there is an alternative from ghcr.io/servercontainers/samba or crazymax/samba
In OSX, it's critical to use volume mount
and avoid using bind mount
as we mentioned above.
In OSX, due to the docker desktop itself is running in VM, it will cause some error like Operation not supported
when binding a local file folder via bind mount
even you set 777
mask on the folder. So it's recommended to use volume mount
to bind to /mnt
in Samba server in OSX.
Furthermore, the Samba server will log such message: error reading meta xattr: Not supported
.
In Linux, it's okay to use either volume mount
or bind mount
.
docker run -it --rm \
--name samba \
-p 139:139 -p 445:445 \
-v mnt:/mnt:z \
dperson/samba \
-p -s "Mount;/mnt;yes;no;yes" -u "bob;bobspasswd" -g "log level = 5"
-s "<Mount;/mnt>;yes;no;yes"
means [browsable:yes;readonly:no;guest:yes]", which will allow the guest to read
and the user to read/write
!
Get the samba server IP address:
$ docker inspect \
-f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' \
samba
172.17.0.2
Start Samba Client in Docker
Use dperson/samba
or busybox
image,
docker run -it --rm --privileged dperson/samba bash
or
docker run -it --rm --privileged busybox sh
Inside the container:
mkdir /smb_share
# mount -t cifs //[server-ip]/[share-path] /[mount-point]
mount -t cifs //172.17.0.2/Mount /smb_share -o rw,username=bob,password=bobspasswd
# write file
echo "xxxx" > /smb_share/f.txt
Start Samba Client which Create Volume in Docker
- Create a CIFS/Samba Volume
docker volume create \
--driver local \
--opt type=cifs \
--opt device=//172.17.0.2/Mount \
--opt o=username=bob,password=bobspasswd \
--name samba-volume
$ docker inspect samba-volume
[
{
"CreatedAt": "2023-08-13T16:24:03Z",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/samba-volume/_data",
"Name": "samba-volume",
"Options": {
"device": "//172.17.0.2/Mount",
"o": "addr=username=bob,password=bobspasswd",
"type": "cifs"
},
"Scope": "local"
}
]
- Start a container using the created volume
samba-volume
.
docker run -it --rm \
-v samba-volume:/mnt \
busybox \
sh
Use Case in Docker Compose
version: "3"
# Inspired by https://github.com/dperson/samba/blob/master/docker-compose.yml
services:
samba:
image: dperson/samba
privileged: true
environment:
TZ: "EST5EDT"
ports:
- "137:137/udp"
- "138:138/udp"
- "139:139/tcp"
- "445:445/tcp"
volumes:
- mnt:/mnt:z
command: '-s "Mount;/mnt;yes;no;yes" -u "bob;bobspasswd" -p'
# networks:
# default:
# ipv4_address: 172.28.0.20
samba-client:
image: busybox
restart: on-failure
volumes:
- samba-volume:/smb_share
# tty: true
command: sleep infinity
depends_on:
- samba
# networks:
# default:
# ipv4_address: 172.28.0.21
# networks:
# default:
# driver: bridge
# ipam:
# config:
# - subnet: 172.28.0.0/16
# gateway: 172.28.0.1
volumes:
mnt:
samba-volume:
driver: local
driver_opts:
type: cifs
# device: "//172.28.0.20/Mount"
# o: "username=bob,password=bobspasswd"
device: "//localhost/Mount"
o: "addr=localhost,username=bob,password=bobspasswd"
Troubleshooting
When you mount an Samba Share in Linux, you may encounter error like failed: Invalid argument
,
bash-5.1# mount -t cifs //172.17.0.2/Mount /mnt/smb_share -o iocharset=utf8,rw,vers=1.0
mount: mounting //172.17.0.2/Mount on /mnt/smb_share failed: Invalid argument
You can use dmesg
to debug,
bash-5.1# dmesg
[317258.750535] CIFS: Attempting to mount \\172.17.0.2\Mount
[317258.752956] CIFS: VFS: No username specified
[317336.240984] cifs: Unknown parameter 'passwd'
[317344.451345] CIFS: Attempting to mount \\172.17.0.2\Mount