Deploying a private Docker image without a registry

Deploying a private Docker image without a registry
Photo by Rubaitul Azad / Unsplash

Have you ever had a project you didn't want to push to the Docker registry? Perhaps it's a private repository in GitHub and you don't want the whole internets to have access to that intel.

Note: If you are looking for a guide on setting up your own local registry, see Running a local Docker registry.

Put together the Docker image

Let's use a simple Dockerfile for this example.

FROM alpine
CMD ["echo", "Hello, World!"]

Use Docker Compose

Docker Compose is fantastic for maintaining the configuration of a Docker application. Although it is not necessary to use Docker Compose, especially for such a simple example, I highly recommend it for keeping a record of the environment variables, ports, volume mounts, etc. that you application needs. Without further ado, here is our Docker Compose file.

version: '3.6'
services:
    clobber:
        container_name: hello
        image: hello

Build the image and deploy

Now this is assuming we have a remote server, either on a local or external network we want to deploy to. It is very handy to trust your local SSH public key on the remote host. Also not necessary, but will save you from having to enter a password every time you want to scp or ssh into the server.

Here's what I have put together in a .sh file. Each step is commented to explain what is going on.

SSH_USER=xxx
SSH_HOST=xxx
HOST_APP_PATH=/host/app/path/
IMAGE_NAME=hello

# Build the Docker image, tagged with the application name
docker build --tag ${IMAGE_NAME} .

# Save the Docker image to a .tar file
docker save -o $(pwd)/${IMAGE_NAME}.tar "${IMAGE_NAME}:latest"

# Secure copy the tar file that contains the image to our server
scp $(pwd)/${IMAGE_NAME}.tar ${SSH_USER}@${SSH_HOST}:${HOST_APP_PATH}${IMAGE_NAME}
# Delete the local copy of the tar file to clean it up
rm -f $(pwd)/${IMAGE_NAME}.tar

# Remove any previously running instances of the image
ssh ${SSH_USER}@${SSH_HOST} "docker rm -f ${APP_NAME} || true"
# Load the image on the host
ssh ${SSH_USER}@${SSH_HOST} "docker load -i ${HOST_APP_PATH}${APP_NAME}.tar"
# Clean up the tar file on the host
ssh ${SSH_USER}@${SSH_HOST} "rm -f ${HOST_APP_PATH}${APP_NAME}.tar"
# Use docker-compose to run the app
ssh ${SSH_USER}@${SSH_HOST} "cd ${HOST_APP_PATH} && docker-compose up --detach --build ${APP_NAME}"

Conclusion

And that's it! We have successfully built, deployed, and run our Docker image on a remote server all without needing a registry. One thing to note is that a registry can definitely be more convenient, especially for keeping around older versions of the application. Now, go to and deploy your apps!