Docker multi-stage builds with Docker Compose

When defining a multi service environment with Docker and Docker Compose, the usual way was to use a Dockerfile for each service, starting with the base image and adding all custom needs:

/env/php/Dockerfile

FROM php:7.2-fpm-alpine3.7

RUN docker-php-ext-install opcache

/env/nginx/Dockerfile

FROM nginx:1.15-alpine

ADD virtual-host.conf /etc/nginx/conf.d/default.conf

Then you could compose all services.

/docker-compose.yml

version: '3'

services:
  php:
    build:
      context: ./env/php
    volumes:
      - ./:/app
    working_dir: /app
    restart: unless-stopped
  nginx:
    build:
      context: ./env/nginx
    volumes:
      - ./:/app
    ports:
      - "80:80"
    restart: unless-stopped

Then Docker 17.05 introduced multi-stage builds, allowing to use one Dockerfile. Another advantage is you can copy files from one image to another at build time.

/env/Dockerfile

FROM php:7.2-fpm-alpine3.7 AS php

RUN docker-php-ext-install opcache


FROM nginx:1.15-alpine AS nginx

ADD virtual-host.conf /etc/nginx/conf.d/default.conf

Each stage of build can be named with “AS”, then referenced in the “build” section of compose by “target” (introduced in Docker Compose 3.4 format).

/docker-compose.yml

version: '3.4'

services:
  php:
    build:
      context: ./env
      target: php
    volumes:
      - ./:/app
    working_dir: /app
    restart: unless-stopped
  nginx:
    build:
      context: ./env
      target: nginx
    volumes:
      - ./:/app
    ports:
      - "80:80"
    restart: unless-stopped

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.