Dockerizing Laravel for production is challenging. In this article, we provide a pattern for dockerizing Laravel that works in production and local.
Unfortunately, many guides explain *just enough* to get your Laravel app working in Docker, but fall short in a few areas.
1. **The resulting image is large.** This makes for slow local setup, especially if you are working at a coffee shop. This large image also makes for a frustrating experience if you are deploying a critical fix to production and it is taking forever to pull the image.
2. **The container needs restarted locally.** Every time you make a change to your Laravel application, you have to rebuild/restart your container to see your changes. When we face this, we end up running Laravel on our local machine and discarding Docker.
3. **The image is configured for production use.** When configured *only* for production use, the docker image is difficult to debug or diagnose. We end up running Laravel locally and use Docker for production. Or we create a separate `local.Dockerfile` that we have to maintain separately.
## Laravel that just works, everywhere
This guide gets you started with docker on a default Laravel app that *just works* locally and in production with the following:
- Server is optimized for [php-fpm](https://php-fpm.org/).
- Static assets and files are automatically added using `ONBUILD` during your docker build process.
- When making code changes, no need to rebuild/restart your container.
- Logs are emitted to stdout/stderr.
- The resulting image is relatively small (~37mb).
- Preconfigured to attach [nginx](https://www.nginx.com/) sidecar container. See below.
This guide assumes the default setup uses a mysql database, but also contains details on how to add other dependencies and databases (e.g. postgres, redis, etc.).
To get started, you will need to add 3 files to our repository.
Create `Dockerfile` in your repository root. This is used to build your local and production docker image.
If you're curious how the base image is configured, visit [https://github.com/nullstone-io/docker-laravel](https://github.com/nullstone-io/docker-laravel).
# Copy code, install dependencies
COPY --chown=nobody:nobody . .
RUN composer install --optimize-autoloader --no-dev
Create `.dockerignore` in your repository root. This will prevent docker from adding sensitive files (e.g. `env`) or PHP packages that are specific to your local system. Don't worry, your vendor directory inside the docker container will be cached.
Create `docker-compose.yml` in your repository root. This stands up a docker container running php containing your laravel app, an nginx container for static assets, and a mysql database container.
test: ["CMD", "mysqladmin", "ping", "-pacme"]
Now, let's launch our Laravel app.
$ docker compose up
Once your container is launched, the application should be reachable from [https://localhost:3000](https://localhost:3000).
## How to extend and configure
If your app did not launch properly, you may need to extend or configure.
Below is a set of common ways to configure and extend Laravel.
### Port 3000 is already in use
By default, this setup uses port 3000, but only by convention.
If you wish to change, refer to line 11 of `docker-compose.yml`.
Change `3000` in the line `- "3000:80"` to an unused port on your system.
### Postgresql instead of mysql
By default, the database is configured for mysql.
If you would like to swap for postgres, you will need swap out the `db` service and reconfigure Laravel to use `pgsql`.
Swap out the `db` service in the `services:` section of `docker-compose.yml`.
Reconfigure Laravel for `pgsql`. Make sure to remove the existing `DATABASE_URL` environment variable.
### Redis for caching
By default, caching is done using the file system.
If you would like to add a redis cache layer, then you will need to add redis to your docker-compose and configure Laravel to use redis inside the docker-compose. Then, you will need to update your `Dockerfile` with the appropriate dependencies.
Add `redis` service under the `services:` section in `docker-compose.yml`.
Configure Laravel to use redis in the existing `app` service under `services:` section in `docker-compose.yml`.
Install `php-redis` extension to your Dockerfile. Warning: This was left out of the base image because it added ~100mb to the image size.
RUN apk add --no-cache pcre-dev $PHPIZE_DEPS \
&& pecl install redis \
&& rm -rf /tmp/pear \
&& docker-php-ext-enable redis.so
## What's next
Hopefully you have a fully functioning Laravel app running in docker on your local machine now. If you still need to configure the OS, you will need to use `apk` (the alpine package manager) instead of `apt`, `apt-get`, or `yum`. As you configure your app in different environments, make sure to follow docker best-practices by using environment variables. This will allow you to easily configure regardless of how your app is launched into production.
If you are interested in launching your newly-dockerized app to a cloud provider, log in at [https://app.nullstone.io](https://app.nullstone.io) and we will launch a secure container app on your cloud provider. We have a reference guide for Laravel in our docs at [https://docs.nullstone.io/frameworks/php/laravel.html](https://docs.nullstone.io/frameworks/php/laravel.html).## Run Laravel anywhereDocker is rapidly becoming the standard for running server applications. One of the key benefits of Docker is portability: the ability to run applications identically regardless of the underlying platform or system. This is especially helpful when running Laravel applications that require installation and configuration of OS-level packages.However, configuring a docker image is a tedious, and many times, frustrating endeavor. ## Laravel is difficult to configure on Docker