Laravel is without doubt one of the hottest PHP frameworks. Based on BuiltWith, Laravel is utilized by greater than 720K web sites world wide. Laravel is an opinionated framework that’s modular, straightforward to make use of, and has a burgeoning ecosystem. On this submit, you’ll discover ways to run Laravel with Docker Compose on Ubuntu 22.04.
To leap forward:
Stipulations
- Ubuntu v22.04 with Docker and Docker Compose put in. For this tutorial, we’ll use Docker v20.10.20 and Docker Compose v2.12.2
- Expertise with Docker
- Some prior information of Laravel can be useful
- Any earlier information of Docker multi-stage builds can be helpful
- Prior information of how Apache works and its relation to PHP
What’s Docker?
Docker is an open supply platform that allows software program engineers to package deal their functions into artifacts known as containers, making them straightforward to ship, and avoiding the issue of including “works on my machine” to your search queries.
So, what are containers? A container is a know-how that allows customers to package deal the entire stack as an artifact. On this context, the entire stack is referring to the working system, the language with any dependencies, your software code, and its dependencies. So on every deployment, you ship the entire stack, not simply the 5 traces of code that modified.
Containers have been round for a very long time, however they had been popularized by Docker in 2014.
Photographs are constructed following the Open Container Initiative (OCI) commonplace in order that they will function anyplace.
Instance Laravel app with Backpack
On this information to working Laravel with Docker and Docker Compose, we’ll use a easy Laravel software. This fundamental Laravel software will use a MySQL database, and to point out how issues work, we’ll use the favored Backpack Laravel package deal that’s used to construct and customise admin panels.
To maintain issues easy as a result of Laravel already comes with a consumer desk and consumer mannequin, we’ll wire that with Backpack to view and edit customers. One caveat right here is that in the event you edit a consumer, that consumer will be unable to log in as a result of the password won’t be encrypted. Nonetheless, that isn’t the priority of this tutorial. For this submit, the main focus is on working a Laravel software with MySQL utilizing Docker and Docker Compose on Ubuntu v22.04.
The complete code for our software is on the market on this GitHub repository. It additionally contains the Dockerfile and the docker-compose.yml file.
The top software will record the customers when visiting http://localhost:8082/admin/consumer
after logging in:
Laravel Sail
The default set up directions for Laravel 9.x include Laravel Sail. Sail is a good product and an integral a part of the Laravel ecosystem. Its GitHub repo states, “Sail supplies a Docker powered native growth expertise for Laravel that’s appropriate with macOS, Home windows (WSL2), and Linux.” So, why are we not utilizing it?
Sail is a good device for a growth setting, however it isn’t fitted to a production-like setting as a result of:
- Sail is simply too general-purpose and contains a number of issues like a database, Redis, and search with MeiliSearch. In manufacturing, these dependencies are offloaded to different companies like RDS or open search
- The Dockerfile is well-suited for a growth setting. It has xdebug, Node.js 16, and yarn. It additionally has shoppers for each MySQL and Node.js, however this stuff add bloat and weight to the container, making it impractical for a production-like setting
- Sail doesn’t use official Docker photos and sews collectively a Docker picture with Ubuntu v22.04 as the bottom picture and provides issues as wanted. It seems to be extra like a digital machine (VM) than an optimized Docker picture
- Sail doesn’t use Docker’s options like Docker multi-stage builds, which can’t solely scale back the dimensions of the picture but in addition make Docker photos effectively optimized for sure environments
This takes us to our subsequent step, the place you’ll clone the repository and perceive the components concerned to run a Laravel app with Docker and Docker Compose.
Organising Docker and Docker Compose
To get began, you possibly can clone the repository with git clone [email protected]:geshan/laravel-backpack-demo.git
. You may go into the folder with cd laravel-backpack-demo
and look across the file construction:
It can look principally like another Laravel 9.x challenge, however one can find another attention-grabbing information. First, there’s the /db/init.sql
file, which is used to load the MySQL Docker container with some consumer and migration knowledge, along with the default Laravel database construction.
Then there are some Docker-specific configuration information within the /docker
folder. As we’ll use the default PHP Docker picture with Apache, an Apache config is there. Equally, for higher efficiency on manufacturing, the Opcache config file can also be included. It won’t be used, however it’s there for reference.
Then, on the root of the challenge, there are three information that may kind the idea of this tutorial. The docker-compose-sail.yml
file is the default Docker Compose file that comes with the Laravel 9.x set up for Sail. It has been renamed from docker-compose.yml
to docker-compose-sail.yml
in order that we will use the docker-compose.yml
file because the default one. After that, we’ve got the Dockerfile that makes use of the multi-stage Docker construct.
Dockerfile for Laravel
The Dockerfile to run Laravel 9.x (9.19 on the time of writing) on Ubuntu 22.04 following the multi-stage construct seems to be like:
FROM composer:2.4 as construct COPY . /app/ RUN composer set up --prefer-dist --no-dev --optimize-autoloader --no-interaction FROM php:8.1-apache-buster as dev ENV APP_ENV=dev ENV APP_DEBUG=true ENV COMPOSER_ALLOW_SUPERUSER=1 RUN apt-get replace && apt-get set up -y zip RUN docker-php-ext-install pdo pdo_mysql COPY . /var/www/html/ COPY --from=construct /usr/bin/composer /usr/bin/composer RUN composer set up --prefer-dist --no-interaction COPY docker/apache/000-default.conf /and so forth/apache2/sites-available/000-default.conf COPY .env.dev /var/www/html/.env RUN php artisan config:cache && php artisan route:cache && chmod 777 -R /var/www/html/storage/ && chown -R www-data:www-data /var/www/ && a2enmod rewrite FROM php:8.1-apache-buster as manufacturing ENV APP_ENV=manufacturing ENV APP_DEBUG=false RUN docker-php-ext-configure opcache --enable-opcache && docker-php-ext-install pdo pdo_mysql COPY docker/php/conf.d/opcache.ini /usr/native/and so forth/php/conf.d/opcache.ini COPY --from=construct /app /var/www/html COPY docker/apache/000-default.conf /and so forth/apache2/sites-available/000-default.conf COPY .env.prod /var/www/html/.env RUN php artisan config:cache && php artisan route:cache && chmod 777 -R /var/www/html/storage/ && chown -R www-data:www-data /var/www/ && a2enmod rewrite
This Dockerfile begins with the construct stage that’s taken from the PHP Composer 2.4 official Docker picture. At this stage, the entire app is copied to the /app
folder contained in the picture, and the Composer set up is run on manufacturing mode with out interplay and abandoning the dev dependencies. So at this level, all of the non-development Composer packages have been put in within the vendor
folder.
Subsequent, you possibly can see the dev
stage. That is the stage that can be used within the docker-compose.yml
file later, as effectively. It begins from the official PHP v8.1 Apache Docker picture. It units some setting variables like APP_ENV
to dev
, APP_DEBUG
to true, and COMPOSER_ALLOW_SUPERUSER
as 1
. These variables are self-explanatory. Then it put in zip, which is required to put in different packages.
As a result of we’re solely utilizing MySQL for this challenge, it installs solely pdo
and pdo_mysql
PHP extensions. Then we get the compose executable from the construct stage. That is one other benefit of utilizing a multi-stage Docker construct. As we’ll use this picture for growth, we set up all dependencies, together with the dev ones, with composer set up
.
After that, we copy the Apache config file to the best location contained in the container from /docker/apache/000-default.conf
. The contents of this file seem like the next:
<VirtualHost *:80> ServerAdmin [email protected] DocumentRoot /var/www/html/public/ <Listing /var/www/> AllowOverride All Require all granted </Listing> ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/entry.log mixed </VirtualHost>
This can be a easy Apache configuration file to serve the web site on port 80 from /var/www/html/public
. It has some extra directives about logs for the digital host. Subsequent, we copy the .env.dev
file as .env
file on the container. This file has all of the configurations, just like the credentials for the MySQL database.
Lastly, we run the common Laravel artisan instructions to config cache, route cache, and make storage writable. Then ensure that the consumer www:knowledge
has the best permissions and allow the rewrite Apache module. It ought to work as a result of the picture has the apache2 foreground because the command.
The subsequent stage is manufacturing
, which additionally begins from the official php:8.1-apache
picture. It configures and allows OPcache for caching in manufacturing. OPcache improves PHP efficiency by storing pre-compiled script bytecode in shared reminiscence, which makes it nice for manufacturing use case.
Then set up pdo
and pdo_mysql
as within the growth stage. The OPcache configs are additionally loaded. If the OPcache configs curiosity you, try this file. Following that, it copies the entire app from the construct stage the place the dev dependencies had been ignored whereas executing compose set up
.
The identical Apache configs are loaded on this Docker stage, too, however the .env.prod
setting variables are copied to the /var/www/html/.env
path. In an actual software, this line would have been omitted in favor of injecting runtime setting variables another means, like utilizing Kubernetes secrets and techniques. Lastly, the identical command is used to make Apache serve our Laravel app. Within the subsequent part, you’ll study concerning the Docker Compose file.
Docker Compose for Laravel
The aformentioned Docker file is constructed and run with a Docker Compose file definition. You may construct and run single containers with the common Docker command. Docker Compose turns out to be useful while you wish to run a number of containers and never sort in lengthy instructions with a number of parameters.
The Docker Compose file is a YAML file to configure your software’s companies. Under is the Docker Compose file to run our Laravel software and the wanted MySQL container. Let’s dissect its contents:
model: '3' companies: app: construct: context: ./ goal: dev volumes: - .:/var/www/html - .env.dev:/var/www/html/.env ports: - "8082:80" setting: - APP_ENV=native - APP_DEBUG=true networks: - laravel depends_on: - mysql mysql: picture: 'mysql/mysql-server:8.0' setting: MYSQL_ROOT_HOST: "%" MYSQL_ROOT_PASSWORD: "root" MYSQL_USER: "laravel" MYSQL_PASSWORD: "FhgVoFuOrWspc3TgBIA2K4dZGuJTPwSYBoLnNckcaxy" MYSQL_DATABASE: "laravel" MYSQL_ALLOW_EMPTY_PASSWORD: 1 ports: - 3906:3306 volumes: - 'mysql8:/var/lib/mysql' - './db/init.sql:/docker-entrypoint-initdb.d/01init.sql' networks: - laravel networks: laravel: driver: bridge volumes: mysql8: driver: native
The Docker Compose file begins with model 3, which has one set of options. Then we outline our companies. The primary one is the app
service, which may have the PHP and Apache server working in the identical containers. For this, we instruct Docker Compose that the Docker file is in the identical listing with context and the goal (learn stage) is dev. So we wish Docker Compose to construct the dev
stage from the multi-stage enabled Dockerfile we mentioned within the earlier part.
On this app
service, we then specify the information we wish to sync from the native machine to the container within the volumes part. We are saying we wish all of the information within the present listing to be synced to /var/www/html
within the container. We additionally specify that the .env.dev
file from native must be synced up with .env
file in the identical path.
Subsequent, we specify that the native port 8082
maps to the container port of 80. On port 80 within the container, the Apache server can be working. After that, we add two setting variables APP_ENV
with the worth native
and APP_DEBUG
with the worth true
. These are set to show errors on the browser in the event that they happen as we’re utilizing this container for native growth.
After that, we specify the community for the app service to be laravel
. Networking in Docker Compose allows methods for a number of companies to speak with one another. For this instance, we’ll use the bridge community, which permits communication between containers related with the identical bridge community. Consequently, we specify that the app container depends_on
MySQL container is outlined subsequent within the file. Quite than a tough dependency, it’s used to manage the sequence of startup and shutdown.
The mysql
service is outlined subsequent within the file. It’s a MySQL server picture supplied by MySQL. For this information, we’re utilizing model 8.0. Right here, some essential setting variables are outlined, just like the ROOT_HOST
, the password for the basis consumer, and one other MySQL consumer and password. The database is specified as laravel
.
Port 3906 on the host machine is mapped to 3306 on the container the place the MySQL server is working. To maintain the info persistent throughout restarts, a quantity named mysql8
is outlined, which is mapped to the default knowledge listing of MySQL at /var/lib/mysql
on the container. One other essential quantity mapping is the ./db/init.sql
file to the entry level. That is performed in order that on the primary begin, our dummy consumer knowledge can be loaded on the empty MySQL server occasion. Subsequent, the community is outlined to be laravel
and the laravel
community is ready as a bridge community.
Final however not the least, the amount for the MySQL server named mysql8
is tagged as a neighborhood driver. Meaning Docker will handle the place to retailer the info. You may study extra concerning the quantity by working the docker quantity ls
command. You too can study different helpful Docker instructions, like Docker photos, logs, and extra. Within the subsequent part, you’ll study concerning the Docker ignore
file.
Don’t ignore the dockerignore
file
Just like how we’ve got the .gitignore
file to exclude sure information from git, we will use the .dockerignore
file to exclude information from being copied to the Docker picture and container. As an illustration, beneath is the .dockerignore
file used on this instance.
.git .env
The above file is instructing Docker to not copy the .git
folder and the .env
file into the container. This may be useful not solely to maintain the container dimension small but in addition to mitigate any safety considerations. Subsequent we’ll construct and run the containers for Laravel on Ubuntu 22.04.
Construct and run domestically
Now we’ve got outlined and described our Dockerfile
and the docker-compose.yml
information. To construct the photographs, you possibly can run the next command:
docker compose construct
It can present the next output to start with:
It’s pulling all of the wanted Docker picture layers from DockerHub to construct the photographs. In my take a look at, it took nearly three minutes to obtain all of the layers. As I used to be utilizing Docker 20.10, it was utilizing BuildKit by default. It ended with the next output:
At this level, it might be nice to get the composer dependencies pulled in domestically as a result of it is going to be mapped in with the volumes within the Docker Compose file. You are able to do it by working:
docker run --rm --interactive --tty --volume $PWD:/app composer set up
This can pull all of the dependencies domestically in your machine and later, when the volumes are mapped, these can be out there on the container too. Take into account, if Docker Compose will not be used or the entire folder will not be mapped as a quantity, this won’t be wanted. It can yield the next output:
Then, to run the container, we will execute:
docker compose up
Relying in your Docker and Docker Compose model, it will also be docker-compose up
if you’re utilizing an older model of Docker Compose. It can yield the next outcome:
This can begin each the companies and their relative containers. As soon as each the containers are up, you possibly can verify the app in your browser at http://localhost:8082
, which is able to present the default Laravel web page:
I’ve added a -
moreover Documentation
to see how the replace works, and it really works high quality. To log in and see the customers, you possibly can navigate to http://localhost:8082/admin/login
and use [email protected]
because the consumer and testpass
because the password, and hit Login:
That is attainable with out working any artisan migrate
because the preliminary knowledge has been loaded with the file ./db/init.sql
, which has two customers. You may see this after you log in and click on Customers on the left:
There you’ve got it! Laravel 9.x working with MySQL on Ubuntu 22.04 with Docker and Docker Compose. Along with being straightforward to arrange, this Docker picture additionally has a stage for manufacturing, which is rather more optimized than Laravel Sail.
Conclusion
On this information, you realized what Docker is. You then realized a few easy Laravel 9.x app with Backpack to show customers. After that, you had been launched to the Docker file and Docker Compose file to run this app utilizing Docker on Ubuntu v22.04. Within the course of, you additionally realized about dockerignore
and how one can construct and run Docker containers for Laravel that work for native growth and in addition assist manufacturing mode.
Comfortable coding!
LogRocket: Full visibility into your net and cell apps
LogRocket is a frontend software monitoring answer that allows you to replay issues as in the event that they occurred in your individual browser. As a substitute of guessing why errors occur, or asking customers for screenshots and log dumps, LogRocket allows you to replay the session to shortly perceive what went mistaken. It really works completely with any app, no matter framework, and has plugins to log further context from Redux, Vuex, and @ngrx/retailer.
Along with logging Redux actions and state, LogRocket data console logs, JavaScript errors, stacktraces, community requests/responses with headers + our bodies, browser metadata, and customized logs. It additionally devices the DOM to document the HTML and CSS on the web page, recreating pixel-perfect movies of even essentially the most advanced single-page and cell apps.