04/06/2019 - DOCKER, PHP
In this example we are going to run composer to install application dependencies then copy vendor
folder and the rest of the application files into container image. With this way our image will always come with the application by default so all we have to do is create a container and start using it. This is a well known practise but I just wanted to touch upon a basic implementation. The main purpose is to isolate application code and not expose it to host OS. I am not going to list the benefits here because they all have been written on the Internet. The main problem with this solution is, the size of the final docker image will depend on the application and vendor
folder size.
.
├── composer.json
├── docker
│ ├── docker-compose.yml
│ ├── Makefile
│ └── php
│ ├── Dockerfile
│ ├── php.ini
│ └── www.conf
├── .dockerignore
├── .gitignore
└── src
└── index.php
I am just showing the content of important files. The rest is not too important.
build:
@docker-compose build
up:
@docker-compose up -d
#
# STAGE 1: composer
#
FROM composer:1.8.5 as composer
# Copy composer files from project root into composer container's working dir
COPY composer.* /app/
# Run composer to build dependencies in vendor folder
RUN set -xe \
&& composer install --no-dev --no-scripts --no-suggest --no-interaction --prefer-dist --optimize-autoloader
# Copy everything from project root into composer container's working dir
COPY . /app
# Generated optimized autoload files containing all classes from vendor folder and project itself
RUN composer dump-autoload --no-dev --optimize --classmap-authoritative
#
# STAGE 2: php
#
FROM php:7.2.13-fpm-alpine3.8
# Set container's working dir
WORKDIR /app
# Copy everything from project root into php container's working dir
COPY . /app
# Copy vendor folder from composer container into php container
COPY --from=composer /app/vendor /app/vendor
# Copy necessary files
COPY docker/php/php.ini /usr/local/etc/php/conf.d/php.override.ini
COPY docker/php/www.conf /usr/local/etc/php-fpm.d/www.conf
CMD ["php-fpm", "--nodaemonize"]
.dockerignore
.gitignore
*.md
.git/
.idea/
.DS_Store/
This is optional but I am leaving it if you want to use it. You could use $ make -sC docker/ build up
command in project root if you don't want to use native docker commands as I am using. Up to you!
version: "3.4"
services:
php:
build:
context: ".."
dockerfile: "docker/php/Dockerfile"
hostname: "php"
$ docker build -t my_php_app:latest -f /absolute/path/to/project/docker/php/Dockerfile .
Successfully built c62632b82433
Successfully tagged my_php_app:latest
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
my_php_app latest c62632b82433 5 minutes ago 77.7MB
$ docker run -itd --name my_php_app my_php_app:latest sh
4ec090d70437cf3312d735f754bcb5abcd96759fd8f76f24fbeb43e42c04f140
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4ec090d70437 my_php_app:latest "docker-php-entrypoi…" 4 seconds ago Up 3 seconds 9000/tcp my_php_app
$ docker exec -it my_php_app sh
/app # ls -l
-rw-r--r-- 1 root root 133 Jun 3 20:23 composer.json
drwxr-xr-x 4 root root 4096 Jun 3 20:33 docker
drwxr-xr-x 2 root root 4096 Jun 3 20:39 src
drwxr-xr-x 4 root root 4096 Jun 3 20:56 vendor
If you run php src/index.php
command inside container, it should work.