# How to deploy Docker Applications with Laravel Forge

Most likely, if you’re reading this, you are a [Laravel Forge](https://forge.laravel.com/) user. Probably, also a Docker user or with interest in it. I was a happy Forge user for a long time in a row until I started using Docker, learned a bunch of its advantages, and ultimately fell in love with such.


Why use Docker for development and deployments, you may ask? I have a bunch of good reasons I could share, but that will be in another post.

#### Pre-requisites for this guide

- You know what [Laravel Forge](https://forge.laravel.com/) is and you are familiar with hosting web applications (notion of server, DNS, )
- You use [Docker](https://www.docker.com/) or [Laravel Sail](https://laravel.com/docs/sail) (which is a CLI and Docker environment for Laravel)
- Servers for demo purposes are now deleted, which will break URLs in the screenshots

### Show me how to get started!

First things first, let's provision a server.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1661494531205/rJU-ot0j7.png align="left")

The relevant thing to learn here is to choose a `Worker Server`. This is because we want the server as clean as possible and ports 80 and 443 available for web hosting. All other VPS options can be sized per your needs.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1661494406893/ufJOsdrpa.png align="left")

So, in a matter of minutes, we have our newly provisioned server! We also know its IP address, so it's time to make the DNS records and point the desired domains to such IP address.


![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1661502921111/qUVfUjGuN.png align="left")

I ended up doing this demo for the blog post with `forge-docker-app.jpat.dev` and `forge-docker-traefik.jpat.dev`, and we will see why in a minute.

So now we need Docker installed in our VPS. We can accomplish this very easily by adding a `Recipe`. Lets do just that and run it in our VPS.
[Copy source code from here](https://github.com/ijpatricio/docker-for-forge/blob/main/resources/forge-recipe.sh)

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1661503626310/HC7UE5Qhb.png align="left")

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1661503522762/xCJloYq2o.png align="left")

By now, we can see the recipe log, or SSH into our server and check `Docker` and `Docker Compose` are installed! 🚀

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1661503869093/4Zsck5onQ.png align="center")

### We are now ready to host Docker containers and Composes

So now we are going to install a "web server", which is [Traefik](https://traefik.io). It's not exactly a webserver; think of this like a Router in your Laravel application. It will take care of the server ports 80 and 443, handle SSL with `Let's Encrypt` automatically, and point the requests to the right Docker application.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1661505042743/xHLBp_bGr.png align="left")

In the simple diagram, we can see a VPS running four containers: Traefik and three containerized apps. For this example, they would be all accessible from the outside, redirecting to SSL if needed and routing the request depending on the required host. It's a very simplified version and much more can happen. Let's keep it like this for simplicity's sake!

### Our entry point to the Apps: Traefik

We can use this repository [ijpatricio/traefik-for-forge](https://github.com/ijpatricio/traefik-for-forge) as is; it's meant to be used by this "common use-case", but of course, feel free to fork, use and customize.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1661505615099/A14DGX5EY.png align="left")

In Forge, inside our server, we go to create a new site, `Traefik`. 

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1661505709512/-ZYuku-gx.png align="left")

Now we install the repository and leave "Install Composer Dependencies" unchecked.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1661505840696/CclALtvGZ.png align="left")

We now have a freshly installed repo! Now let's do some preparations. We can SSH into the machine and run the commands in the site's directory or run right from the `Commands` in the Forge UI. I absolutely recommend SSH into the machine and running it from there.

```
docker network ls | grep web || docker network create web

cd ~/traefik 

cp .env.example .env

cp docker-compose.prod.yml docker-compose.yml

# Choose a username and a strong password
./Taskfile auth username password
```

Let's now fill the environment variables in the Forge UI. Example below.


![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1661511491818/ai8QUmtFE.png align="left")

We also need to change the deploy script to:

```
cd /home/forge/traefik

git pull origin $FORGE_SITE_BRANCH

cp docker-compose.prod.yml docker-compose.yml

docker-compose up -d --remove-orphans
```


![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1661508313462/Zx8ytvvQE.png align="left")

It should now look something like the above. We can press `Deploy now`.


![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1661508378055/IGB2qWWT5.png align="left")

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1661508457600/1DVI9rb4k.png align="left")

With any luck, deploy must be complete now, and the deploy log will look something like the above, and a `docker ps` on the machine will show the running container, and mapped ports :)

Furthermore, we can visit `https://forge-docker-traefik.jpat.dev/` and check that is password protected.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1661511611900/EdSeX6iX4.png align="left")

After entering credentials, we have our SSL secured Traefik dashboard.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1661511678040/4gRVH2hxK.png align="left")


### Deploying Dockerized Applications

Woohooo!! Glad you made it so far! By now, we can already deploy applications just by using a `docker-compose.yml` file!

From here, we can use public images or adds login(s) to use with private registries.

Here, continue the journey on [How to Dockerize a Laravel App to run in Laravel Forge](https://blog.jpat.dev/how-to-dockerize-a-laravel-app-to-run-in-laravel-forge).


Happy coding, happy deploys!!

Patricio
