To get started, you’ll need to create a containerized environment able to execute PHP and Composer, the PHP dependency management tool. Then, you’ll be able to bootstrap the new Laravel application from scratch, without the need to have a local PHP environment installed on your local machine or development server.
In this guide, streamlined instructions will be provided on how to set this environment up based on our tutorial on How To Install Laravel with Docker Compose on Ubuntu 20.04. Please refer to that tutorial for more detailed instructions on each of the options used within the Docker Compose file that will be provided in this guide.
Create a new directory for your application in your home folder:
- mkdir ~/landing-laravel
- cd ~/landing-laravel
Next, you’ll create the docker-compose.yml
file that will define the containerized environment. In this file, you’ll set up a service named app
, which will be based on a custom Docker image built with a Dockerfile you’ll set up later on.
The build arguments user
and uid
, both defined in the docker-compose.yml
file and used in the Dockerfile at build time, should be changed to reflect your own username and uid on your local machine or development server. To find out your current user’s uid, type:
- echo $UID
Output1000
The user
and uid
variables will be available at build time and will be used in the Dockerfile to create a new user in the app
service with the same username and uid as your current system user on your local machine or development server. This will avoid permission and ownership issues when working with application files both from the container as well as from the host that executes Docker.
Create a new docker-compose.yml
file using your text editor of choice. Here, nano
is used:
- nano docker-compose.yml
Copy the following content to this file, and don’t forget to replace the highlighted values with appropriate values depending on your own username and uid on the system that runs Docker:
version: "3.7"
services:
app:
build:
args:
user: sammy
uid: 1000
context: ./
dockerfile: Dockerfile
image: landing-app
restart: unless-stopped
working_dir: /var/www/
volumes:
- ./:/var/www
networks:
- landing
networks:
landing:
driver: bridge
Save and close the file when you are done. If you are using nano
, you can do that by pressing CTRL
+X
, then Y
and ENTER
to confirm.
Next, you’ll set up the Dockerfile that is referenced in the docker-compose.yml
file, which will set up a custom image for the app
service:
- nano Dockerfile
This Dockerfile extends from the default php:7.4-fpm
Docker image. It uses the user
and uid
variables to create a new user able to execute Artisan and Composer commands. It also installs a few PHP dependencies that are required by Laravel, and the Composer executable.
Copy the following content to your Dockerfile:
FROM php:7.4-fpm
# Arguments defined in docker-compose.yml
ARG user
ARG uid
# Install system dependencies
RUN apt-get update && apt-get install -y \
git \
curl \
libpng-dev \
libonig-dev \
libxml2-dev \
zip \
unzip
# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
# Install PHP extensions
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
# Get latest Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# Create system user to run Composer and Artisan Commands
RUN useradd -G www-data,root -u $uid -d /home/$user $user
RUN mkdir -p /home/$user/.composer && \
chown -R $user:$user /home/$user
# Set working directory
WORKDIR /var/www
USER $user
Save and close the file when you’re done. Next, you can bring your environment up with:
- docker-compose up -d
This command will execute Docker Compose in detached mode, which means it will run in the background. The first time you bring an environment up with a custom image, Docker Compose will automatically build the image for you before creating the required containers. This might take a few moments to finish. You’ll see output similar to this:
OutputCreating network "landing-laravel_landing" with driver "bridge"
Building app
Step 1/11 : FROM php:7.4-fpm
---> fa37bd6db22a
...
Step 10/11 : WORKDIR /var/www
---> Using cache
---> 769afd5d44d8
Step 11/11 : USER $user
---> Using cache
---> 841eb5852b69
Successfully built 841eb5852b69
Successfully tagged landing-app:latest
WARNING: Image for service app was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating landing-laravel_app_1 ... done
You can verify that your environment is up and running with:
- docker-compose ps
Output Name Command State Ports
------------------------------------------------------------------------
landing-laravel_app_1 docker-php-entrypoint php-fpm Up 9000/tcp
Once the app
service is up, you can run Composer, the PHP dependency management tool, to bootstrap a new Laravel application. In order to do that, you’ll use docker compose exec
to run commands on the app
service, where PHP is installed.
The following command will use Docker Compose to execute composer create-project
, which will bootstrap a fresh installation of Laravel based on the laravel/laravel
package:
- docker-compose exec app composer create-project laravel/laravel --prefer-dist application
Creating a "laravel/laravel" project at "./application"
Installing laravel/laravel (v8.4.0)
- Downloading laravel/laravel (v8.4.0)
- Installing laravel/laravel (v8.4.0): Extracting archive
Created project in /var/www/application
> @php -r "file_exists('.env') || copy('.env.example', '.env');"
Loading composer repositories with package information
Updating dependencies
Lock file operations: 104 installs, 0 updates, 0 removals
…
Package manifest generated successfully.
71 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
> @php artisan key:generate --ansi
Application key set successfully.
This installation creates a new .env
file based on the default .env.example
file that comes with Laravel. The .env
file contains database credentials and other sensitive application settings, and should be unique per environment where the app runs. You’ll come back to edit this file after you finish setting up the development environment.
Next, copy the application files to the same directory as the docker-compose.yml
file, so that you can share Laravel’s environment variables file with Docker Compose. Then, you can remove the application
directory created by Composer:
- cp -rT application .
- rm -rfv application
Your application is now bootstrapped, but you’ll need to include a couple services in the Docker Compose file in order to be able to access the app from a browser. An nginx
service will serve the application using the Nginx web server, and a db
service will host the application’s MySQL database.
First, bring your environment down with:
- docker-compose down
OutputStopping landing-laravel_app_1 ... done
Removing landing-laravel_app_1 ... done
Removing network landing-laravel_landing
This will remove all containers and networks associated with this environment. Before editing your docker-compose.yml
file to add the new services, create a new directory to share configuration files with containers. You’ll need this to properly set up Nginx to handle the Laravel PHP application.
- mkdir -p docker-compose/nginx
Next, create a new landing-laravel.conf
file containing a custom Nginx server block. Later on, you’ll set up a volume to share this file within the nginx
service container.
Open a new Nginx configuration file with:
- nano docker-compose/nginx/landing-laravel.conf
The following server block configures Nginx to serve a Laravel application using an external service (app
) to handle PHP code. Copy this content to your own Nginx configuration file:
server {
listen 80;
index index.php index.html;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /var/www/public;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass app:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
gzip_static on;
}
}
Save and close the file when you’re done.
Next, open your docker-compose.yml
file:
- nano docker-compose.yml
Include the following configuration for the nginx
service, at the same level as the previously configured app
service. This will create a new service based on the nginx:alpine
image, and all requests on port 8000
of the host where Docker is running will be redirected to port 80
in the service container. In addition to the application files, you’ll also share a volume containing Nginx’s configuration file for a Laravel application:
nginx:
image: nginx:alpine
restart: unless-stopped
ports:
- 8000:80
volumes:
- ./:/var/www
- ./docker-compose/nginx:/etc/nginx/conf.d/
networks:
- landing
Then, include the following configuration block for the db
service. This will create a service based on the default MySQL 8 image, and pull in the values defined in Laravel’s environment file to set up database access:
db:
image: mysql:8
restart: unless-stopped
environment:
MYSQL_DATABASE: ${DB_DATABASE}
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
MYSQL_PASSWORD: ${DB_PASSWORD}
MYSQL_USER: ${DB_USERNAME}
networks:
- landing
This is how your updated docker-compose.yml
file should look like once you’re finished:
version: "3.7"
services:
app:
build:
args:
user: sammy
uid: 1000
context: ./
dockerfile: Dockerfile
image: landing-app
restart: unless-stopped
working_dir: /var/www/
volumes:
- ./:/var/www
networks:
- landing
nginx:
image: nginx:alpine
restart: unless-stopped
ports:
- 8000:80
volumes:
- ./:/var/www
- ./docker-compose/nginx:/etc/nginx/conf.d/
networks:
- landing
db:
image: mysql:8
restart: unless-stopped
environment:
MYSQL_DATABASE: ${DB_DATABASE}
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
MYSQL_PASSWORD: ${DB_PASSWORD}
MYSQL_USER: ${DB_USERNAME}
networks:
- landing
networks:
landing:
driver: bridge
Note: for more detailed information about containerizing Laravel environments, including explanations about shared volumes and networks, please refer to our full guide on How To Install Laravel with Docker Compose on Ubuntu 20.04.
Save and close the file when you’re done editing. Lastly, update your Laravel dot env file (.env
) to point the MySQL database host configuration to the host where the MySQL service will be running, called db
:
- nano .env
The .env
file that is automatically generated by Composer upon installation comes with some default values that you might want to change, such as the APP_NAME
and the APP_URL
. The database DB_HOST
variable must be changed to point to the service where MySQL will be running, and you can reference it by its service name, as defined in the docker-compose.yml
file. In this example, you’ve used db
as the name for the database service, so this will be available in the containerized network as a host named db
.
Change your .env
accordingly, using the following example as base. The highlighted values were updated here to reflect the state of the application under development:
APP_NAME=LandingLaravel
APP_ENV=local
APP_KEY=base64:ffYPNP8kPeQDf8gE/qh3kWjk59p6gFY66kCKhhKUa2w=
APP_DEBUG=true
APP_URL=http://localhost:8000
LOG_CHANNEL=stack
LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=landing-db
DB_USERNAME=landing-user
DB_PASSWORD=dev-password
...
You don’t need to change any other sections of this file, but feel free to tweak to your specific use case.
Save and close the file when you’re done editing its contents.
You can now bring the updated environment up with:
- docker-compose up -d
OutputCreating network "landing-laravel_landing" with driver "bridge"
Creating landing-laravel_app_1 ... done
Creating landing-laravel_db_1 ... done
Creating landing-laravel_nginx_1 ... done
With the full environment up, you can now point your browser to localhost
or your remote server’s IP address, on port 8000
:
http://localhost:8000
If everything works as expected, you’ll see a page like this:
In the next part of this series, you’ll create a database migration to set up a links table.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
Laravel is an open-source PHP framework that provides a set of tools and resources to build modern PHP applications. In this project-based tutorial series, you’ll build a Links Landing Page application with the Laravel framework, using a containerized PHP development environment managed by Docker Compose.
At the end, you’ll have a one-page website built with Laravel and managed via Artisan commands where you can share relevant links to an audience on social channels and presentations.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Sign up for Infrastructure as a Newsletter.
Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
Regards for this good guide. All works fine, but i’ve problmems with debugger configuration (vscode in ubuntu 20.04). This is json configuration, what’s wrong? { “name”: “Listen for Xdebug”, “pathMappings”: { “/var/www”: “${workspaceRoot}” }, “type”: “php”, “request”: “launch”, “stopOnEntry”: true, “port”: 9000 }
I am running Windows 10, is UID the same as SID (Security ID) because UID is not available in Windows?