Laravel + Docker Using Alpine

Muhammad Bagus Ramadhan
4 min readOct 11, 2017

There are already a lot of images built for Laravel to run using Alpine image. This time I tried to make my own docker container for Laravel using Alpine.

Step 1 — Laravel Installation

I’m using the usual way to install Laravel.

composer create-project laravel/laravel docker-alpine

That would create a docker-alpine directory of Laravel latest release with dependencies installed.

Step 2 — Create docker-compose.yml file

First, go to docker-alpine directory and create docker-compose.yml file, start it with:

version: '2'services:
# our services goes here...

I will separate this into 3 services:

  • app container to run and execute PHP script,
  • web container to run NGINX,
  • database container to handle our database.

App Service

Add this lines below services:

app service @ docker-compose.yml

Notes:

  • dockerfile: app.dockerfile Dockerfile used to build our app service.
  • working_dir: /var/www/html set default working directory inside container.
  • ./:/var/www/html mount current directory, in this case all of docker-alpine content, to /var/www/html/ inside the container.
  • Set environment to match database container that will be added later.

Now create app.dockerfile forapp container.

Notes:

  • php:7-fpm-alpine is used here.
  • The rest is used to compile all php extension needed, and remove the apk cache to reduce container size.
  • For line 31, we need to copy supervisord-app.conf to /etc/supervisord.conf. It will be used by supervisor for its configuration. It will later create supervisord.log in root directory.
  • Update, there is an issue when installing mcrypt using php 7.2 because it is not provided with the php 7.2 source. Use pecl install mcrypt-1.0.1 then enabled it with docker-php-ext-enable mcrypt.

NGINX-Alpine

The next container is web container to handle serving static files, and pass-through request that will be handled by Laravel.

web service @ docker-compose.yml

Notes:

  • It is the same as app container before, but web.dockerfile will be used instead.
  • app will be used for volumes_from because web container will inherit /var/www/html directory from app container.
  • map port 8080 on the host to 80 in the container so we can use 0.0.0.0:8080 or localhost:8080 to access the container.

Next, create web.dockerfile.

Notes:

  • nginx-alpine will be used here.
  • supervisor will be installed here to log nginx activity.
  • On line 5 add new user and group to because nginx:alpine doesn’t come with default user.
  • Add nginx.conf to configure server.
  • The rest is the same like app.dockerfile

Below is supervisord-web.conf file.

And createnginx.conf.

Notes:

  • On events you can add any events configuration or you can leave it blank inside. I’ve tried adding and leaving it blank and nginx still working fine.
  • At line 15 and 19 I add some locationto add header for .css and .js files because in my case, nginx read it as plain text files.
  • And the rest is just standard nginx configuration.

MYSQL

Now, create database container to handle our data. We create a new volume so our files created in the container persist and allowing us to stop or restart our service without losing our data.

mysql service @ docker-compose.yml

Notes:

  • In the bottom, make new volume. In this case I create dbdata. This volume will be used later to mount directory /var/lib/mysql which defined at database volumes.
  • Image used here is mysql:5.7. In this test I am using Laravel 5.5 and I encountered an error when doing artisan migrate command. Explanation in this link
  • Set required environment variables, and make sure that your Larave .env database configuration to follow this environment configuration later.
  • Set port mapping 33061 on the host to 3306 of the container. This will allow external tools to access the database.

Final docker-compose.yml file will looks like this:

Starting Services

From the first step to mysql part, make sure that all of these file is exist inside root directory:

  • docker-compose.yml
  • app.dockerfile and web.dockerfile
  • supervisord-app.conf and supervisord-web.conf
  • nginx.conf

Then run docker-compose -f docker-compose.yml up. It will take some time for all of the service to download all of the package it need to set the container up.

Final Step, Laravel Setup

This steps below is automatically done if you grab Laravel source code using composer create-project or if you already did composer install inside your working directory.

  1. Copy .env.example => .env.
  2. Run php artisan key:generate this can be done inside the container using docker exec -it app sh where app is our Laravel php container or by using docker exec app php artisan key:generate.
  3. Run php artisan optimize this can be done just like above.

After that you can tried to test your Laravel installation by going to http://0.0.0.0:8080 or http://localhost:8080.

Important things in development

  • If you always using artisan you can use that command inside your container by using docker exec -it <your-container-name> sh or by using docker exec <your-container-name> php artisan <artisan-command>. Using -it means it will execute your given command interactively inside container.
  • Running composer inside your container is possible if you add `COPY --from=composer:1.5 /usr/bin/composer /usr/bin/composer inside your app.dockerfile, but you will encounter with permission issue. You can use composer image to do this.

Last but not least, thanks to Shane Osbourne for this awesome guide!

Happy Coding

--

--