0% found this document useful (0 votes)
33 views9 pages

Dockerize A Laravel 11 App

This document provides a comprehensive guide on how to dockerize a Laravel 11 application using Docker Compose in 2024. It details the necessary configuration files, the Dockerfile for building the application, the docker-compose.yml for defining services, and the Nginx server configuration. Additionally, it covers environment variable setup, building the Docker image, and accessing the application after deployment.

Uploaded by

xhartono
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
33 views9 pages

Dockerize A Laravel 11 App

This document provides a comprehensive guide on how to dockerize a Laravel 11 application using Docker Compose in 2024. It details the necessary configuration files, the Dockerfile for building the application, the docker-compose.yml for defining services, and the Nginx server configuration. Additionally, it covers environment variable setup, building the Docker image, and accessing the application after deployment.

Uploaded by

xhartono
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 9

Dockerize a Laravel 11 app

Dockerizing a Laravel application is not as simple as it seems, which is why today I will guide you
through the process of creating a Docker image for Laravel 11 in 2024.

To do this, we will configure a complete environment using Docker Compose, ensuring that our
Laravel application is ready for deployment in any environment.

1. Create the necessary configuration files


To start, make sure to create the following files in your project:

./deploy/docker-compose.yml
./deploy/Dockerfile
./deploy/nginx.conf
./deploy/php.ini
./.dockerignore

These files contain the necessary configuration to create the Docker image and manage the
containers.

Using the deploy directory is a personal convention; you can choose any name you prefer.
However, make sure the configurations shown below match the path where you saved the
files.

1.1 Build the Dockerfile


The Dockerfile defines the development environment for our Laravel application. In this case,
we will divide it into two stages: one to build the application and another to run it in production
(not necessarily) as follows:

1 # deploy/Dockerfile
2
3 # stage 1: build stage
4 FROM php:8.3-fpm-alpine as build
5
6 # installing system dependencies and php extensions
7 RUN apk add --no-cache \
8 zip \
9 libzip-dev \
10 freetype \
11 libjpeg-turbo \
12 libpng \
13 freetype-dev \
14 libjpeg-turbo-dev \
15 libpng-dev \
16 nodejs \
17 npm \
18 && docker-php-ext-configure zip \
19 && docker-php-ext-install zip pdo pdo_mysql \
20 && docker-php-ext-configure gd --with-freetype=/usr/include/ --with-
jpeg=/usr/include/ \
21 && docker-php-ext-install -j$(nproc) gd \
22 && docker-php-ext-enable gd
23
24 # install composer
25 COPY --from=composer:2.7.6 /usr/bin/composer /usr/bin/composer
26
27 WORKDIR /var/www/html
28
29 # copy necessary files and change permissions
30 COPY . .
31 RUN chown -R www-data:www-data /var/www/html \
32 && chmod -R 775 /var/www/html/storage \
33 && chmod -R 775 /var/www/html/bootstrap/cache
34
35 # install php and node.js dependencies
36 RUN composer install --no-dev --prefer-dist \
37 && npm install \
38 && npm run build
39
40 RUN chown -R www-data:www-data /var/www/html/vendor \
41 && chmod -R 775 /var/www/html/vendor
42
43 # stage 2: production stage
44 FROM php:8.3-fpm-alpine
45
46 # install nginx
47 RUN apk add --no-cache \
48 zip \
49 libzip-dev \
50 freetype \
51 libjpeg-turbo \
52 libpng \
53 freetype-dev \
54 libjpeg-turbo-dev \
55 libpng-dev \
56 oniguruma-dev \
57 gettext-dev \
58 freetype-dev \
59 nginx \
60 && docker-php-ext-configure zip \
61 && docker-php-ext-install zip pdo pdo_mysql \
62 && docker-php-ext-configure gd --with-freetype=/usr/include/ --with-
jpeg=/usr/include/ \
63 && docker-php-ext-install -j$(nproc) gd \
64 && docker-php-ext-enable gd \
65 && docker-php-ext-install bcmath \
66 && docker-php-ext-enable bcmath \
67 && docker-php-ext-install exif \
68 && docker-php-ext-enable exif \
69 && docker-php-ext-install gettext \
70 && docker-php-ext-enable gettext \
71 && docker-php-ext-install opcache \
72 && docker-php-ext-enable opcache \
73 && rm -rf /var/cache/apk/*
74
75 # copy files from the build stage
76 COPY --from=build /var/www/html /var/www/html
77 COPY ./deploy/nginx.conf /etc/nginx/http.d/default.conf
78 COPY ./deploy/php.ini "$PHP_INI_DIR/conf.d/app.ini"
79
80 WORKDIR /var/www/html
81
82 # add all folders where files are being stored that require persistence.
if needed, otherwise remove this line.
83 VOLUME ["/var/www/html/storage/app"]
84
85 CMD ["sh", "-c", "nginx && php-fpm"]

Remember that if your application has additional PHP extensions, you should add them in this file
in the dependency installation section. This might be necessary only in the production stage, but
there could be cases where it's required in the build stage.

1.2 Add the docker-compose.yml file


This file defines the services needed to run our Laravel application in Docker. In the following
docker-compose.yml, we define the service for our Laravel application, as well as the service for
the MySQL database.

Remember to follow step 2 to create the environment variables, this is very important for
your application to work correctly.

1 services:
2 laravel:
3 restart: unless-stopped
4 container_name: laravelapp
5 build:
6 context: ../
7 dockerfile: ./deploy/Dockerfile
8 # allocate as many volumes as necessary, if needed.
9 volumes:
10 - ../storage/app:/var/www/html/storage/app
11 environment:
12 APP_NAME: ${APP_NAME}
13 APP_ENV: ${APP_ENV}
14 APP_DEBUG: ${APP_DEBUG}
15 APP_KEY: ${APP_KEY}
16 APP_VERSION: ${APP_VERSION}
17 APP_URL: ${APP_URL}
18 DB_CONNECTION: mysql
19 DB_HOST: database
20 DB_PORT: 3306
21 DB_DATABASE: ${DB_DATABASE}
22 DB_USERNAME: ${DB_USERNAME}
23 DB_PASSWORD: ${DB_PASSWORD}
24 MAIL_MAILER: ${MAIL_MAILER}
25 MAIL_HOST: ${MAIL_HOST}
26 MAIL_PORT: ${MAIL_PORT}
27 MAIL_USERNAME: ${MAIL_USERNAME}
28 MAIL_PASSWORD: ${MAIL_PASSWORD}
29 MAIL_ENCRYPTION: ${MAIL_ENCRYPTION}
30 MAIL_FROM_ADDRESS: ${MAIL_FROM_ADDRESS}
31 MAIL_FROM_NAME: ${MAIL_FROM_NAME}
32 ports:
33 - "8080:80"
34 networks:
35 - n-laravel
36 depends_on:
37 - database
38
39 database:
40 restart: unless-stopped
41 image: mariadb:lts-jammy
42 volumes:
43 - v-database:/var/lib/mysql
44 environment:
45 MARIADB_DATABASE: ${DB_DATABASE}
46 MARIADB_USER: ${DB_USERNAME}
47 MARIADB_PASSWORD: ${DB_PASSWORD}
48 MARIADB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
49 networks:
50 - n-laravel
51
52 volumes:
53 v-database:
54
55
56 networks:
57 n-laravel:
58 driver: bridge

In the volume configuration, you can add or remove the volumes you need. In this case, only the
volume for the storage/app folder is being added, assuming it might be the only folder needing
persistence. Also, if you don't need it, you can remove it.

Similarly, you don't necessarily have to use a directory as a volume; you can use a Docker volume
without any problem.

1.3 Nginx server configuration


Next, we configure the nginx.conf file to serve our Laravel application. This file defines the
Nginx server configuration and how to handle requests to the application.

1 # deploy/nginx.conf
2
3 server {
4 listen 80 default_server;
5 listen [::]:80 default_server;
6
7 root /var/www/html/public;
8 client_max_body_size 10M;
9 add_header X-Frame-Options "SAMEORIGIN";
10 add_header X-Content-Type-Options "nosniff";
11
12 index index.php;
13
14 charset utf-8;
15
16 location / {
17 try_files $uri $uri/ /index.php?$query_string;
18 }
19
20 location = /favicon.ico {
21 access_log off; log_not_found off;
22 }
23 location = /robots.txt {
24 access_log off; log_not_found off;
25 }
26
27 error_page 404 /index.php;
28
29 location ~ \.php$ {
30 fastcgi_pass 127.0.0.1:9000;
31 fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
32 include fastcgi_params;
33 }
34 }

1.4 PHP Configuration


In case you need to configure PHP, you can do it through the php.ini file. As shown in the
following example, where the maximum file upload size is set to 10MB.

1 # deploy/php.ini
2 upload_max_filesize = 10M

1.5 Add the .dockerignore file


This file specifies which files or directories should be ignored by Docker when building the image.
For example, it would not be appropriate to copy vendor for compatibility, time, etc.

1 # .dockerignore
2 /deploy/docker-compose.yml
3 /deploy/Dockerfile
4 /.phpunit.cache
5 /node_modules
6 /public/build
7 /public/hot
8 /public/storage
9 /public/bucket
10 /storage/*.key
11 /vendor
12 .env
13 .env.example
14 .env.backup
15 .env.production
16 .phpunit.result.cache
17 Homestead.json
18 Homestead.yaml
19 auth.json
20 npm-debug.log
21 yarn-error.log
22 /.fleet
23 /.idea
24 /.vscode
25 .git

2. Environment variable configuration


By default, when creating a Laravel project, a .env file with the necessary environment variables
for development is created.

But; in case you don't have it, you must create a .env file in the root of your project and define
the necessary environment variables for your application. Here is a link showing an example of
what your .env file should look like: https://github.com/laravel/laravel/blob/11.x/.env.example

Among all this configuration, it is important to edit the database settings. Which by default before
editing would look like this:

1 DB_CONNECTION=sqlite
2 # DB_HOST=127.0.0.1
3 # DB_PORT=3306
4 # DB_DATABASE=laravel
5 # DB_USERNAME=root
6 # DB_PASSWORD=

And we need to change it to:

1 DB_CONNECTION=sqlite
2 # DB_HOST=127.0.0.1
3 # DB_PORT=3306
4 DB_DATABASE=laravel
5 DB_USERNAME=admin
6 DB_PASSWORD=admin
7 DB_ROOT_PASSWORD=root

In this case, we are ignoring the following configurations: DB_CONNECTION , DB_HOST , and
DB_PORT . The reason is that these values are already defined in the docker-compose.yml file.

We are also adding: DB_ROOT_PASSWORD , which is vital for the MySQL image to be built correctly,
as it requires a password for the root user.
Remember that these environment variables are sensitive and should not be shared
publicly. Additionally, passwords should be secure.

3. Building the Docker image


With everything configured previously, it is time to build the Docker image. For this, we will use
the following commands:

1. Build and bring up the containers:

1 docker compose -f deploy/docker-compose.yml --env-file ./.env up --build

2. Run Laravel migrations:

1 docker exec -t laravelapp php artisan migrate

3. Run Laravel seeders:

In this step, it is not only enough to run the command, but also if you are using the
"fakerphp/faker" library, you need to modify the composer.json file to move the library from
the list of development dependencies to the list of production dependencies.

This happens because when creating the image, it is indicated not to install development
dependencies and therefore when running the command, it will show an error that it cannot find
the library.

Example of how the composer.json file should look:

Before:

1 {
2 "require": {
3 ...
4 },
5 "require-dev": {
6 "fakerphp/faker": "^1.23"
7 }
8 }

After:
1 {
2 "require": {
3 ...
4 "fakerphp/faker": "^1.23"
5 },
6 "require-dev": {
7 ...
8 }
9 }

It is important to clarify that ... means you may have more dependencies in your file.
Therefore, you should not copy them.

And now, we can run the command:

1 docker exec -t laravelapp php artisan db:seed

4. Configure volumes
This step only applies if you are using a directory as a volume. If this is not your case, you
can skip this step.

As you know, in the Dockerfile we are defining a volume for the storage/app folder of our
application. And similarly, within the docker-compose.yml file, the volume is configured as a
directory to store persistent files.

However; you may encounter a problem where when writing to this directory, you will likely get a
permissions error.

This happens because Nginx does not have sufficient permissions to write to the folder. My
solution to this problem is to run the following command to modify and add those permissions:

1 # first: change group (nginx)


2 sudo chown -R :81 storage/app
3 # second: change permissions
4 sudo chmod -R 775 storage/app

If you're curious about why the number 81 , it's because it is the nginx group ID in Alpine
Linux.

5. Access the application


Once you have built the image and brought up the containers using the docker compose
command, you can check that your application is working properly in your browser.

Make sure to access the URL http://localhost:8080 and if everything is fine, you will see the
home page of your Laravel application.
Conclusion
With these steps, you will have created a Docker image for your Laravel 11 application in 2024.
Now you can deploy your application in any environment without worrying about dependencies
or server configuration.

It is worth noting that you should carefully verify if you need to add more dependencies in the
Dockerfile as well as modify other configurations that may be necessary for your application,
both in Nginx, php.ini , and even the version of PHP you are using, it might be necessary to
change it.

You might also like