Using a Service to Start a Container

I have been attempting to get around the missing --privileged option in a docker service while trying to setup a swarm. I have read elsewhere people having success about getting a service to launch a container on the node where they could bypass this method since they could just create a normal container with this option. What I can’t find is any example of how one would accomplish this.

Can anybody provide an example of a docker service that that could start an existing container on the same node? Is this even possible?

1 Like

Hey! I’ve actually had to do exactly that. As you may have guessed it isn’t a perfect work-around, but could be close enough for a number of applications. Here is the code:

Dockerfile:

FROM docker
	
	# Environment Variables
	ENV CONTAINER_NAME="" \
	    FORCE_UPDATE="true"
	
	# Docker entrypoint
	COPY docker-entrypoint.sh /docker-entrypoint.sh
	RUN chmod 744 /docker-entrypoint.sh
	
	ENTRYPOINT ["sh", "/docker-entrypoint.sh"]

docker-entrypoint.sh:

#!/bin/bash
	
	####
	# Start container
	####
	
	log_prefix='[docker-run-d]'
	
	echo "$log_prefix Starting up"
	
	# If the container name has been set
	if [ -n "$CONTAINER_NAME" ]; then
	
	    # If FORCE_UPDATE is true
	    if [ "$FORCE_UPDATE" = "true" ]; then
	
	        # Stop and remove the container ( in case it already exists )
	        echo "$log_prefix FORCE_UPDATE is true: removing container '$CONTAINER_NAME' if it exists"
	        docker stop $CONTAINER_NAME
	        docker rm $CONTAINER_NAME
	    fi
	
	    # Start the container ( in case it is not already running )
	    echo "$log_prefix Starting container: '$CONTAINER_NAME'"
	    eval "docker run -d --name $CONTAINER_NAME $1"
	
	    # Follow the container logs
	    echo "$log_prefix Starting container logs:"
	    docker logs -f $CONTAINER_NAME &
	
	    # Trap the kill signal
	    trap 'echo "$log_prefix Got kill signal: Stopping and removing container"; docker stop $CONTAINER_NAME; docker rm $CONTAINER_NAME; exit 0' SIGTERM SIGINT
	else
	
	    # Run the container without specifying a name and record the container id
	    echo "$log_prefix Starting container"
	    eval "docker run -d $1 > /container_id"
	
	    # Follow the container logs
	    echo "$log_prefix Starting container logs:"
	    docker logs -f $(cat /container_id) &
	
	    # Trap the kill signal
	    trap 'echo "$log_prefix Got kill signal: Stopping and removing container"; docker stop $(cat /container_id); docker rm $(cat /container_id); exit 0' SIGTERM SIGINT
	fi
	
	
	# Wait for signal
	while true; do sleep 1; done

So if I follow this script correctly, this is the service you would run in a swarm by setting the container name in the build file to start on the host when it’s started. What I don’t see is how that service would have access to a different container outside of itself on the host. Is there specific permissions you are setting to give the service access to that?

Ah, here is the README content. If you still have questions afterwards just ask.

Docker Run -d

This is a very simple container that will run a container that you specify. This may seem completely ridiculous, but it does have a very specific use case: running a privileged container as a Swarm service. Docker Swarm does not allow running privileged containers as services. This container is a workaround. Create a swarm service that runs this container and mounts the Docker socket into it ( something that is allowed on swarm ), and pass in whatever parameters you want ( including the possibility of the --privilged flag ) to a docker run -d command that will be run as a standalone container on the host.

When this container receives a SIGTERM or SIGINT signal it will docker stop and docker rm the container that you tell it to run. This makes it behave as much like a Swarm service as possible. Don’t forget that the container that you run is a standalone container. If you want the container to run on the same network as your swarm stack you must specify that in the run command. For example: --net stackname_networkname. Another thing to be aware of is that killing the docker-run-d container without allowing it to gracefully shutdown, such as when you run docker kill, will cause the container that the docker-run-d container starts to be left running. One way to make this more controllable is to set the CONTAINER_NAME environment variable ( see below ).

There are many possible scenarios for other potentially unexpected behaviors when using this container. This is not a perfect workaround for the Swarm privileges issues and will likely not work for many different use cases. You should be aware of possible problems that may depend on the particular docker run command that you pass to this container.

Environment Variables

CONTAINER_NAME

Setting the CONTAINER_NAME environment variable allows the docker-run-d container to keep track of the container that it is supposed to be running and allows it to gracefully recover from being unexpectedly terminated by a docker kill or by an unexpected system shutdown. When the CONTAINER_NAME is set it will add a --name flag to the docker run command; you should not add one to the command manually. In addition to setting the --name of the container the docker-run-d container will stop, remove, and re-create the container of the given name if a container with that name is found at startup. In other words it will force updating the container run command to make sure that it is up-to-date. You can override this behavior by setting the FORCE_UPDATE environment variable.

Default: null string

FORCE_UPDATE

When FORCE_UPDATE is true the docker-run-d container will remove and re-create the container with the given CONTAINER_NAME when it starts up. This setting only applies when CONTAINER_NAME is set. Setting FORCE_UPDATE to anything other than true will prevent a container of the given name from being removed and updated when the docker-run-d container starts.

Default: true