How to Dockerize a Laravel App to run in Laravel Forge

ยท

3 min read

So I'm almost sure you were already in the previous blog post. If not, you might want to visit How to deploy Docker Applications with Laravel Forge.

  • Note: Servers for demo purposes are now deleted, which will break URLs in the screenshots

This will be a "show by example", so let's build an App from scratch and deploy it!

Have your application ready

Let's make a fresh Laravel Application with Sail Builder

curl -s "https://laravel.build/example-docker-forge?with=mysql,redis" | bash

cd example-docker-forge

sail up -d

When it finishes, you should be up and running! ๐Ÿš€

image.png

Let's get some more Docker magic into it!

So now, let's make this really easy, by using a package I built. Run the following commands:

composer require ijpatricio/docker-for-forge --dev

php artisan dockerEnv:install

It will ask you a few questions:

  • App Domain: The host that will be registered with Traefik, routing requests from such host to that container (service).
  • App Name and Vendor Name are used to populate the docker-compose.yml

image.png

For the time being, it makes a single container, with Supervisor (as in Laravel Sail) guaranteeing the webserver running (Nginx), the PHP interpreter (PHP-fpm), and cron (scheduling). Take into consideration using this "as-is" just with a single container. More complex scenarios are possible; this is keeping everything simple for the sake of understanding the basics!

I could go into details, but everything is taken care of regarding permissions so that Laravel Forge can read the logs in the UI, we can mount a storage folder, can run commands, and more. Maybe in another post, I could explain things further!

The build will use multiple steps, keeping the image lean. Builds frontend, installs composer dependencies, and more. The sensible basics have been covered. Customize at taste!

Also, .env variables can be used to change some values, but I kept things in the repo for simplicity.

Before committing the code, let's do one more thing:

mv docker-compose.yml docker-compose.dev.yml

echo "docker-compose.yml" >> .gitignore

This is so that each environment will use a specific docker-compose. For example, we locally have a database, but in production, we most likely have that service separated in another VPS.

Commit your code, let's deploy!

On to Laravel Forge

Back on the UI, let's add a website.

image.png

And we should get something like this. Use your repository. Un-check "Install Composer Dependencies".

image.png

We arrive on the App tab. We now change the deploy script accordingly.

image.png

And here is the code:

cd /home/forge/example-docker-forge

git pull origin $FORGE_SITE_BRANCH

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

docker-compose build

docker-compose up -d --remove-orphans

# Run commands as `forge` user, not `root`
function forgeCmd {
    docker-compose exec example-docker-forge bash -c "gosu forge bash -c \"$@\""
}

# Run this just the first time, so it doesn't keep changing
forgeCmd "php artisan key:generate"

# add route cache, db migrate, and your other commands as you see fit!
# forgeCmd "php artisan migrate --force"

Check that environment variables are properly set!

image.png

The build can now run!

image.png

Ta-daaaa ๐Ÿš€

Logs are available from the UI:

image.png

Storage folder is mounted into the container. This app has its own instance of Redis, so no need for prefixes and so on!

And of course, our website is live, and SSL secured:

image.png

Happy coding, happy deploys ๐Ÿ˜ƒ

ย