When we talk about deploying to production with Docker, we refer to the process of moving your container architecture to a remote and public server.
You’ve done your work. You have your docker-compose.yml flawless. You run docker compose up -d, open your browser at localhost:8080, and your application shines in all its glory… on your computer.
Now what? How do I get my clients or the rest of the world to access my-project.com and see this? Do I have to install Docker there? How do I transfer my source code or database to the server?
Moving from “Localhost” to “Internet” often feels daunting. But precisely, container technology makes this the cleanest, most predictable, and most professional deployment method out there (that’s why we got into this mess!).
Today we’re going to learn how to prepare a cloud server and the strategy for transferring our project 👇.
The Server: Your New Home in the Cloud (VPS)
For your application to be online 24/7, you need a computer that never shuts down. The cheapest and most professional way to do this is to rent a VPS (Virtual Private Server).
A VPS is simply a slice of a giant server in the cloud. Providers like Hetzner, DigitalOcean, or OVH rent you one for about €4 or €5 per month.
When you sign up, you choose an operating system (e.g., Ubuntu Server) and the provider will give you two things:
- A public IP address (e.g.,
198.51.100.xxx). - A password (or SSH key) for the
rootuser.
Open your terminal and connect to your remote server using SSH:
Congratulations! You’re now inside the computer that will host your project.
Preparing the Ground: Docker on the Server
The server comes completely empty. The advantage of using containers is that you only need to install one thing on your server: Docker.
No more installing PHP, Node, databases, or fighting with dependencies on the server. You run the official Docker installation script for Linux, and that’s it:
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
Your server is now ready to understand any docker-compose.yml you throw at it.
How Do I Get My Project There?
Now for the “hard part” (which isn’t hard). You have your code on your laptop… how do you upload it? There are three main strategies, from the most basic to the most privacy-conscious:
You upload your code to a private GitHub or GitLab repository. You SSH into your server, clone the repository, and build the image right there.
On the server: You only upload the docker-compose.yml file. When you run docker compose up, the server downloads the compiled image.
git clone https://github.com/your-username/your-repo.git
cd your-repo
docker compose up -d --build
✅Pros: Very easy to understand.
❌Cons: The server consumes a lot of CPU compiling, and your source code resides physically on the public server (security risk if hacked).
Instead of sending your source code to the server, you compile it on your computer and upload the already finished image to a third-party registry (like Docker Hub).
On your computer: Build and upload.
docker build -t your-username/my-app:v1 .
docker push your-username/my-app:v1
On the server: You only upload the docker-compose.yml file. When you run docker compose up, the server downloads the compiled image.
✅Pros: Zero source code exposure, the server doesn’t struggle with compiling.
❌Cons: You depend on an external company to host your images.
If you don’t like depending on third parties (and rightfully so), Docker allows you to “package” a compiled image into a standard compressed file, send it yourself, and load it onto the server. Zero external dependencies.
On your computer: Build the image and export it to a .tar file.
docker build -t my-app:v1 .
docker save -o my-app-v1.tar my-app:v1
Transfer: Send the file directly to your server using the scp (Secure Copy) command.
scp my-app-v1.tar [email protected]:/root/
On the server: Load the file back into the Docker engine.
docker load -i my-app-v1.tar
✅Pros: Absolute privacy. You don’t need internet on the server to download images, ideal for high-security environments (air-gapped).
❌Cons: You have to manually upload a large file every time you update.
The most common workflow is probably to upload the code to a repository (Github, Gitlab, Azure Devops) and have them compile the code and send the image to a Docker Hub.
This is still scenario 2, but instead of your computer, it’s an external service that compiles the app (and with one more dependency 😉).
The Reverse Proxy: Domain and Automatic HTTPS
Your container is already running on the server on a port (e.g., 8080). If you go to the IP http://198.51.100.xxx:8080, you’ll see your website.
But you want people to access mydomain.com with HTTPS security… For this, we use the final piece: The Reverse Proxy.
Tools like Traefik or Nginx Proxy Manager (which are installed as another Docker container) act as the “gatekeepers” of your server.
They listen on the official internet ports (80 and 443). When someone visits mydomain.com, the Reverse Proxy receives the request, contacts the certificate authority (Let’s Encrypt), obtains a free SSL certificate automatically, and redirects the traffic to your container on port 8080.
