Running Laravel and Angularjs on Docker



I did a previous post about running Symfony2 and Angularjs on Docker. Well, I've recently created a similar project, specific to Laravel which can be found here.

I'll touch briefly again on how that's working.

First up we have a docker-compose.yml file, which defines our global environment settings and global variables etc. As well as defining which images you're either pulling in or building from source.

# Your main webserver instance, running nginx and php5-fpm
# Links third party services such as MySQL etc.
# Finally links your codebases as volumes to the webserver
webserver:  
  build: images/webserver
  ports:
    - "80:80"
  links:
    - mysql:mysql
    - mongodb:mongodb
    - memcached:memcached
    - redis:redis
    - elasticsearch:elasticsearch
    - beanstalkd:beanstalkd
  volumes_from:
    - apidata
    - admindata
    - frontenddata

# Api codebase
apidata:  
  image: busybox
  volumes:
    - "sites/api/api.conf:/etc/nginx/sites-enabled/api.conf"
    - "www/api/:/var/www/api/"

# Angular project
admindata:  
  image: busybox
  volumes:
    - "sites/admin/admin.conf:/etc/nginx/sites-enabled/admin.conf"
    - "www/admin/:/var/www/admin/"

# Angular project 2
frontenddata:  
  image: busybox
  volumes:
    - "sites/frontend/frontend.conf:/etc/nginx/sites-enabled/frontend.conf"
    - "www/frontend/:/var/www/frontend/"

mysql:  
  image: tutum/mysql
  ports:
    - "3306:3306"
  environment:
    MYSQL_PASS: "password"
    ON_CREATE_DB: "apidb"

mongodb:  
  image: tutum/mongodb
  ports:
    - "27017:27017"
    - "28017:28017"
  environment:
    MONGODB_PASS: password

beanstalkd:  
  image: chriskite/beanstalkd
  ports: 
    - "11300:11300"

memcached:  
  image: tutum/memcached
  ports:
    - "11211:11211"
  environment:
    MEMCACHED_PASS: password

redis:  
  image: tutum/redis
  ports:
    - "6379:6379"
  environment:
    REDIS_PASS: password

elasticsearch:  
  image: tutum/elasticsearch
  ports:
    - "9200:9200"
  environment:
    ELASTICSEARCH_USER: admin
    ELASTICSEARCH_PASS: password

And the webserver Dockerfile.

This is pretty straight forward, we pull in ubuntu, install the latest stable version of nginx and its dependencies as well as doing any other configuration such as setting the nginx user.

Then we install a selection of commonly used php extensions and of course compose.

Then we configure any directories we need for nginx and our codebases to sit etc.

Finally we start nginx and php5-fpm.

FROM ubuntu:trusty

MAINTAINER Ewan Valentine <ewan@theladbible.com>

# Install Nginx.
RUN \  
  apt-get install -y software-properties-common && \
  add-apt-repository -y ppa:nginx/stable && \
  apt-get update && \
  apt-get install -y nginx && \
  rm -rf /var/lib/apt/lists/* && \
  echo "\ndaemon off;" >> /etc/nginx/nginx.conf && \
  chown -R www-data:www-data /var/lib/nginx

# Only use stable sources
RUN rm -rf /etc/apt/sources.list.d/proposed.list

# Install packages
RUN apt-get update && \  
  apt-get install -y \
  curl \
  wget \
  php5-fpm \
  php5-mysql \
  php5-mcrypt \
  php5-gd \
  php5-memcached \
  php5-curl \
  php5-xdebug

RUN curl -sS https://getcomposer.org/installer | php  
RUN mv composer.phar /usr/local/bin/composer

# Create required directories
RUN mkdir -p /etc/nginx && \  
    mkdir -p /var/run/php5-fpm && \
    mkdir -p /etc/nginx/sites-enabled && \
    mkdir -p /var/log/nginx

RUN rm -rf /etc/nginx/sites-enabled/default

# Add configuration files
ADD php.ini /etc/php5/fpm/conf.d/40-custom.ini

# Expose volumes
VOLUME ["/var/www", "/etc/nginx/sites-enabled"]

EXPOSE 80

WORKDIR /var/www

CMD service php5-fpm start && nginx  

We also include a php.ini file so we can configure php on the fly.

To get it fired up:

$ docker-compose build docker-compose up
$ cp -r www/api/.env.example www/api/.env $ docker-compose run webserver bash -c "cd api && php artisan migrate && composer update"

Then set your vhosts

# Test Project
192.168.59.103 api.test.com  
192.168.59.103 admin.test.com  
192.168.59.103 frontend.test.com  

I made a few small tweaks in Laravel's .env file, here's an example

APP_ENV=local  
APP_DEBUG=true  
APP_KEY=whatevs

DB_HOST=mysql_1  
DB_DATABASE=apidb  
DB_USERNAME=admin  
DB_PASSWORD=password

CACHE_DRIVER=redis  
SESSION_DRIVER=redis  
QUEUE_DRIVER=beanstalkd

REDIS_HOST=redis_1  
BEANSTALKD_HOST=beanstalkd_1  
MEMCACHED_HOST=memcached_1  

You'll notice I'm using hostnames for services such as mysql like mysql_1 that's because they are environment variables created by Docker. Because the internal network IP's change for each container, those environment variables resolve those automatically.

I reflected that flexibility in Laravels config files. For example, I made Redis's host configurable from the .env file

 'redis' => [

        'cluster' => false,

        'default' => [
            'host'     => env('REDIS_HOST', '127.0.0.1'),
            'port'     => 6379,
            'database' => 0,
            'password' => env('REDIS_PASSWORD', 'password'),
        ],

    ],

Check out the full source code here!