Docker setup for a Laravel+Vue project
Here I want to publish a simple yet functional setup for a dockerized app with Laravel backend and Vue.JS frontend.
What did I want?
- Simple setup for development with docker-compose
- With Laravel acting as pure backend
- XDebug
- Vue to take over all the frontend needs
- Hot reload for the Vue app
- No SSL in local development environment
What did I come up with?
- Nginx acting as web trafic router, proxying to frontend or backend, depending on request URI
- Backend service: Laravel running
artisan serve
- Frontend service: Vue-cli running
npm run serve
Directory/repository structure
Legend: d: directory
, f: file
d: backend -> git submodule, points to laravel API repo
d: frontend -> git submodule, points to Vue app repo
d: etc
d: nginx
d: conf.d
f: default.conf.nginx
d: php
f: .gitignore
d: dockerize
d: backend
f: Dockerfile
f: docker-compose.yml
f: Makefile
As you can see, this project itself mainly serves as an infrastructure project which connects our services and glues them all together. Developer may clone a single repo and work in it, if that’s sufficient. Normally, though, everyone would want to clone this infra repo and start docker-compose stack to have all the project services running locally.
Nginx router
docker-compose part:
www:
image: nginx:alpine
volumes:
- ./etc/nginx/conf.d/default.conf.nginx:/etc/nginx/conf.d/default.conf
ports:
- 80:80
depends_on:
- backend
- frontend
…and the configuration, of course.
server {
listen 80;
server_name frontend;
error_log /var/log/nginx/error.log debug;
location / {
proxy_pass http://frontend:8080;
}
location /sockjs-node {
proxy_pass http://frontend:8080;
proxy_set_header Host $host;
# below lines make ws://localhost/sockjs-node/... URLs work, enabling hot-reload
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
location /api/ {
# on the backend side, the request URI will _NOT_ contain the /api prefix,
# which is what we want for a pure-api project
proxy_pass http://backend:8080/;
proxy_set_header Host localhost;
}
}
Backend
I added a Dockerfile
for the backend, because official PHP images don’t include XDebug. Also, later on, I wanted to add redis extension:
FROM php:fpm-alpine
RUN apk add --no-cache $PHPIZE_DEPS oniguruma-dev libzip-dev curl-dev \
&& docker-php-ext-install pdo_mysql mbstring zip curl \
&& pecl install xdebug redis \
&& docker-php-ext-enable xdebug redis
RUN mkdir /app
VOLUME /app
WORKDIR /app
EXPOSE 8080
CMD php artisan serve --host=0.0.0.0 --port=8080
And of course, we build this image using docker-compose, that is, we automate and simultaneously document this process with a declarative approach:
backend:
build:
context: dockerize/backend
# this way container interacts with host on behalf of current user.
# !!! NOTE: $UID is a _shell_ variable, not an environment variable!
# To make it available as a shell var, make sure you have this in your ~/.bashrc (./.zshrc etc):
# export UID="$UID"
user: ${UID}:${UID}
volumes:
- ./backend:/app
# custom adjustments to php.ini
# i. e. "xdebug.remote_host" to debug the dockerized app
- ./etc/php:/usr/local/etc/php/local.conf.d/
environment:
# add our custom config files for the php to scan
PHP_INI_SCAN_DIR: "/usr/local/etc/php/conf.d/:/usr/local/etc/php/local.conf.d/"
command: "php artisan serve --host=0.0.0.0 --port=8080"
The laravel app itself is beyond the scope of this post, I will simply assume it’s
a standard app built with composer create-project laravel/laravel
or alike.
Take a note of the comment above the user: ${UID}
directive
Frontend
Again, the Vue app itself is out of scope. I created mine with @vue/cli
, using the vue-cli-service
.
Docker-compose:
frontend:
image: node:current-alpine
user: ${UID}:${UID}
working_dir: /home/node/app
volumes:
- ./frontend:/home/node/app
environment:
NODE_ENV: development
command: "npm run serve"