Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

samba-share #40

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
15 changes: 15 additions & 0 deletions samba-share/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
FROM debian:stable
LABEL CMDBUILD="docker build -t niccokunzmann/samba-share https://raw.githubusercontent.com/niccokunzmann/dockerfiles/master/samba-share/Dockerfile"
LABEL CMDRUN="docker run niccokunzmann/samba-share"

MAINTAINER Sven Dowideit <[email protected]> (@SvenDowideit)
MAINTAINER Nicco Kunzmann <[email protected]> (@dannhaltohneson)

# gettext for envsubst
RUN apt-get update && \
apt-get install -yq samba gettext
ADD run.sh /run.sh
ADD setup-samba-share.sh /setup-samba-share.sh
ADD samba-share.sh /samba-share.sh

ENTRYPOINT ["/run.sh"]
56 changes: 56 additions & 0 deletions samba-share/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@


# Samba Docker volume sharing plugin

Sharing a Docker container's volume should be as simple as `docker run niccokunzmann/samba-share <container> | sh`.

This 'plugin' will create and configure a samba server container that auto-creates shares for all
the volumes attached to the specified container.

## Usage

Possible scenarios are

- `docker run niccokunzmann/samba-share <container> | sh` shares the volumes of `<container>`.
- `docker run niccokunzmann/samba-share` reminds the user what the options are.
- Additional parameters can be [passed as environment variable](https://docs.docker.com/engine/reference/run/#env-environment-variables) and can be combined. Possible names are USER PASSWORD USERID GROUP READONLY. Example:

docker run -e READONLY=yes niccokunzmann/samba-share <container> | sh

## Try it out

Create a volume in my-data and share its content via samba

# Make a volume container (only need to do this once)
docker run -v /data --name my-data busybox true
# Share it using Samba (Windows file sharing)
docker run niccokunzmann/samba-share my-data | sh

## How it works

The `niccokunzmann/samba-share` container uses the bind-mounted docker client and socket to introspect
the configuration of the specified container, and then uses that information to setup a new container
that is `--volumes-from` setup to give it access.

## Tested

-
Client:
Version: 1.9.1
API version: 1.21
Go version: go1.4.2
Git commit: a34a1d5
Built: Fri Nov 20 13:20:08 UTC 2015
OS/Arch: linux/amd64

Server:
Version: 1.9.1
API version: 1.21
Go version: go1.4.2
Git commit: a34a1d5
Built: Fri Nov 20 13:20:08 UTC 2015
OS/Arch: linux/amd64

## Credits

This was derived from [`svendowideit/samba`](https://github.com/SvenDowideit/dockerfiles/tree/master/samba) to [`niccokunzmann/samba-share`](https://github.com/niccokunzmann/dockerfiles/tree/master/samba-share) because of [Issue 29](https://github.com/SvenDowideit/dockerfiles/issues/29).
19 changes: 19 additions & 0 deletions samba-share/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/bash
#
# run.sh does one of these
# - execute samba
# - run sh commands to set up samba
#
set -e

if [ "$1" == "--start" ]
then
shift 1
/samba-share.sh "$@"
else
/setup-samba-share.sh "$@"
fi




48 changes: 48 additions & 0 deletions samba-share/samba-share.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/bin/bash
#set -e

USER=${USER:-"root"}
PASSWORD=${PASSWORD:-"tcuser"}
USERID=${USERID:-1000}
GROUP=${GROUP:-"root"}
READONLY=${READONLY:-"no"}

CONTAINER="$1"
shift 1

echo "Setting loglevel to 0."
sed 's/\[global\]/\[global\]\n log level = 0/' -i.bak /etc/samba/smb.conf

echo "Setting up samba configuration for container \"$CONTAINER\" and volumes "$@"."

for VOLUME in "$@"
do
echo "Adding volume \"$VOLUME\"."

VOLUME_NAME=`echo "$VOLUME" | sed "s/\///" | tr '[\/<>:"\\|?*+;,=]' '_'`

echo "[$VOLUME_NAME]
comment = ${VOLUME_NAME} volume from ${CONTAINER}
read only = ${READONLY}
locking = no
path = ${VOLUME}
force user = ${USER}
force group = ${GROUP}
guest ok = yes
map archive = no
map system = no
map hidden = no" >> /etc/samba/smb.conf
done

cat /etc/samba/smb.conf

if ! id -u $USER > /dev/null 2>&1
then
useradd $USER --uid $USERID --user-group --password $PASSWORD --home-dir /
fi
/etc/init.d/samba start
echo "Watching /var/log/samba/*"
tail -f /var/log/samba/*
# This should allow the samba-server to be removed by --rm.
exit 0

187 changes: 187 additions & 0 deletions samba-share/setup-samba-share.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
#!/bin/bash
set -e

docker_host_execute() {
echo "$@"
}
output() {
docker_host_execute echo "$@"
}
error() {
output "ERROR: $@"
}

print_usage() {
output "Please run with:"
output " docker run niccokunzmann/samba-share \"$container\" | sh"
output ""
output " OR - depending on your Docker Host's location of its docker binary"
output ""
output " DOCKER=/usr/local/bin/docker /usr/local/bin/docker run niccokunzmann/samba-share \"$container\" | /bin/sh"
output "Maybe even add sudo."
}

usage() {
output
[ -n "$1" ] && error "$@"
print_usage
output
docker_host_execute exit 1
exit 1
}


# remove the default shell print
docker_host_execute PS1=

docker_host_execute "
output() {
echo "$@"
}
docker_host_execute() {
true
}"


# copy functions to sh
# http://stackoverflow.com/a/9895178
declare -f usage
declare -f print_usage
declare -f error

# parse parameters
container=$1

# check parameters
if [ -z "$container" ]
then
# some spacing in case this is not piped to sh
docker_host_execute
docker_host_execute
docker_host_execute # Hello user! Read the message below:
container="<container_name>"
usage "No container name given. Replace <container_name> with the name of the container to share volumes from."
fi

# create environment for sh
docker_host_execute "container=$container"
docker_host_execute "sambaContainer=`grep cpu[^a-zA-Z\d] /proc/1/cgroup | grep -oE '[0-9a-fA-F]{64}'`"
# It could be that parameters were passed as
# docker run -e USER=... niccokunzmann/samba-share \"$container\" | sh
# We set them like this so they must be named explicitely and
# are not accidentially taken from the environment.
docker_host_execute "USER=$USER"
docker_host_execute "PASSWORD=$PASSWORD"
docker_host_execute "USERID=$USERID"
docker_host_execute "GROUP=$GROUP"
docker_host_execute "READONLY=$READONLY"

# define function for sh instead of a string for better syntax highlighting
execute_in_sh() {

if [ -z "$DOCKER" ]
then
DOCKER=docker
fi

if ! type "$DOCKER" 2>>/dev/null 1>>/dev/null
then
usage "Could run docker command as \"$DOCKER\". Please specify where to find the docker binary."
fi

# check if variable transfer from host to shell worked
if [ -z "$container" ] || [ -z "$sambaContainer" ]
then
error "Could not transfer necessary variables form docker container. Not your fault."
exit 1
fi

if ! $DOCKER inspect "$container" 1>>/dev/null 2>>/dev/null
then
usage "Container \"$container\" does not exist."
fi

volumes=`$DOCKER inspect --format='{{range \$k,\$v := .Config.Volumes}}{{println \$k}}{{end}}' "$container" | grep -v -E "^$"
$DOCKER inspect --format='{{range \$k,\$v := .Volumes}}{{println \$k}}{{end}}' "$container" | grep -v -E "^$"`

if [ -z "$volumes" ]
then
usage "Could not detect any volumes to share in container \"$container\"."
fi

sambaImage=`$DOCKER inspect --format='{{.Config.Image}}' "$sambaContainer"`
if [ -z "$sambaImage" ]
then
error "Could not find samba image of container \"$sambaContainer\"."
exit 1
fi

server_container_name=samba-server

if $DOCKER inspect --format "{{.State.Running}}" "$server_container_name" >/dev/null 2>&1
then
echo "Stopping and removing existing server."
$DOCKER stop "$server_container_name" > /dev/null 2>&1
$DOCKER rm "$server_container_name" >/dev/null 2>&1
fi

echo "Starting \"$server_container_name\" container sharing the volumes" $volumes "of container \"${container}\"."

# from here we should pass the work off to the real samba container
# I'm running this in the background rather than using run -d, so that --rm will still work
$DOCKER run --rm --name "$server_container_name" \
--expose 137 -p 137:137 \
--expose 138 -p 138:138 \
--expose 139 -p 139:139 \
--expose 445 -p 445:445 \
-e USER -e PASSWORD -e USERID -e GROUP -e READONLY \
--volumes-from "$container" \
"$sambaImage" --start "$container" $volumes > /dev/null 2>&1&

# wait for the container to finish and remove it
$DOCKER wait "$sambaContainer" 2>>/dev/null 1>>/dev/null
$DOCKER rm "$sambaContainer" 2>>/dev/null 1>>/dev/null

# give advice
# http://stackoverflow.com/a/20686101
ips="`docker inspect --format ' {{ .NetworkSettings.IPAddress }}' "$server_container_name"`"
example_ip="`echo "$ips" | head -n1 | grep -o -E '\S+'`"
echo ""
echo "# run 'docker logs \"$server_container_name\"' to view the samba logs"
echo ""
echo "================================================"
echo ""
echo "Your data volumes (" $volumes ") should now be accessible at "'\''\'"$example_ip"'\'" as 'guest' user (no password)"
echo ""
echo "For example, on OSX, using a typical boot2docker vm:"
echo " goto Go|Connect to Server in Finder"
echo " enter 'cifs://$example_ip"
echo " hit the 'Connect' button"
echo " select the volumes you want to mount"
echo " choose the 'Guest' radiobox and connect"
echo
echo "Or on Linux:"
echo " mount -t cifs //$example_ip/data /mnt/data -o username=guest"
echo
echo "Or on Windows:"
echo " Enter "'\''\'"$example_ip"'\'"data' into Explorer"
echo " Log in as Guest - no password"
echo ""
echo "Ip addresses: "
echo "$ips"
echo ""
exit 0
}

# copy execute_in_sh to sh
declare -f execute_in_sh

# execute execute_in_sh in sh
docker_host_execute execute_in_sh

# finally, if you did not pipe it to sh, you may need some output
output() {
echo "# $@"
}
print_usage