Jeffrey Winn's Blog

Assorted thoughts and information of nominal value

View on GitHub

From my experience, Docker (which is great, in the right hands) on Windows is not usable in the real world. You can’t really expose ports, and there is no loopback IP. So, I took to installing my main Docker on my CentOS server. Some working notes and examples of how I’ve used it so far…

OWASP Juice-Shop setup example:

The first thing we (often) want to do is to create a local storage space for our data. If we do not do this, the data in the container will not persist. That means, the next time we restart the container, it will go back to its original state, losing any data we’ve added since its creation. That’s bad.

I have found that when creating the volume for our container, it is wise to specifically locate the volume, rather than letting the Docker daemon do it for us.

To do this, I turned to a guide I found and created my volume in this way:

docker volume create -d local-persist -o mountpoint=/home/docker/juice-shop --name=juice-shop

…this places the actual volume in a place I want it (/home/docker/juice-shop) rather than in the “normal” place on this CentOS machine (/var/lib/docker/volumes).

Creating the rest of the bits needed to best utilize the volume is routine. Create local link to volume:

mkdir /home/jwinn/juice-shop

…this space if supposed to be a mount location for changes to the data. I honestly have yet to do much research into this or the usefulness of it, but there you go.

Now, run the initial instance (will pull if needed)…this will also attach to the created storage, name the container, expose port 3000 and set the container to always be running):

docker run -d --name juice-shop --mount source=juice-shop,target=/home/jwinn/juice-shop -p 3000:3000 --restart always bkimminich/juice-shop

Start as needed (optional, as it should always be running):

docker start juice-shop

Adding additional services at startup:

Add something like this custom script (initial credit goes here) as /docker-startextras.sh:

#!/bin/bash

# Start the first process
service ssh start

# Start the second process
service php7.3-fpm start

# Naive check runs checks once a minute to see if either of the processes exited.
# This illustrates part of the heavy lifting you need to do if you want to run
# more than one service in a container. The container exits with an error
# if it detects that either of the processes has exited.
# Otherwise it loops forever, waking up every 60 seconds

while sleep 60; do
        ps aux |grep ssh |grep -q -v grep
        PROCESS_1_STATUS=$?
        ps aux |grep php7.3-fpm |grep -q -v grep
        PROCESS_2_STATUS=$?
        # If the greps above find anything, they exit with 0 status
        # If they are not both 0, then something is wrong
        if [ $PROCESS_1_STATUS -ne 0 -o $PROCESS_2_STATUS -ne 0 ]; then
                echo "A Service process has exited...automatically restarting..."
                exit 1
        fi
done

Call this custom script by additions to /docker-entrypoint.sh (before the ending ‘exec “$@”‘).

Create volume for storage (e.g., user account):

docker volume create juice-shop

Create local link to volume: __

mkdir /home/jwinn/juice-shop

Run initial instance (will pull if needed)…this will also attache to the created storage, name the container, expose port 3000 and set the container to always be running):

docker run -d --name juice-shop --mount source=juice-shop,target=/home/jwinn/juice-shop -p 3000:3000 --restart always bkimminich/juice-shop

Start as needed (optional, as it should always be running):

docker start juice-shop

To rename image name (not hostname, etc.):_

_

docker tag  <old> <new>

and then

docker rmi <old>

To keep docker container “as is” to do something more with it (such as add exposed ports):

docker commit nginx nginx2

…note that this should not be needed if you we are using a mounted volume for this container. If you trust that.

Then, add the new image from this copy…

docker run -d --name nginx2 -p 2222:22 -p 443:443 -p 21:2121 --mount source=nginx,target=/home/jwinn/nginx -h nginx --restart always nginx2

…then remove original container that was cloned…

docker rm nginx

…and rename the image back to the original…

docker container rename nginx2 nginx

…the rename the tag and remove unneeded tag…

docker tag nginx2 nginx
docker rmi nginx2

…I have found that this last step does not always work.

Backup a Docker container remotely

In this example, backing up a NGINX (web server) container via Secure Shell (SSH) where a key has been pre-shared. This could also be placed in your crontab to perform on a regular basis. Note that this does not get your volume data, if any. I had a hard time with that, and the supposed volume area was empty anyway. The script:

#!/bin/bash

# Get date for timestamping...
datenow=$(date +'%m-%d-at-%H-%M')
echo "Date and time: $datenow"

# Back up docker instance...
echo "Backup up container..."
/usr/bin/docker commit -p nginx "nginx-backup-$datenow"

# Save this commit to a tar file...
echo "Converting to file..."
/usr/bin/docker save -o "nginx-backup-$datenow.tar" "nginx-backup-$datenow"

echo "Compressing backup..."
/usr/bin/gzip "nginx-backup-$datenow.tar"

# Send file to Nextcloud backup area...
echo "Sending to Nextcloud backup area via SSH..."
/usr/bin/scp "nginx-backup-$datenow.tar.gz" www-data@dantooine:/data/jwinn/files/Backups/.

# Now, completely without checking to see if it made it, delete the original!
echo "Removing original file..."
/usr/bin/rm "nginx-backup-$datenow.tar.gz"

…Get back