skip to Main Content

I’m new to Docker and want to build the image myself (nginx + php-fpm + mariadb + phpadmin).

I want to have Xdebug so I’ve a Dockerfile to customize the php-fpm image.

And then I run into a problem (same as here) when I execute

docker-compose --build

or

docker-compose up --build

The image was built ok first time, but for next times it fails because the php-fpm somehow ended up with already installed xdebug:

+ pecl install xdebug
pecl/xdebug is already installed and is the same as the released version 3.1.5
install failed

It is like the image comes from cache but Dockerfile is still applied.

I’ve used the solution from that post but I am clearly missing something, it should not be like that. What am I doing wrong?

My docker-compose:

version: "3.7"

services:

  web:
    image: nginx:1.17
    ports:
      - 8080:80
    volumes:
      - ../logs:/var/log/nginx/  
      - ../wordpress:/var/www/myapp
      - type: bind
        source: ./site.conf
        target: /etc/nginx/conf.d/default.conf  
    depends_on:
      - php
      - mariadb

  php:
    image: php:7.4-fpm
    build: 
      context: ./php
    volumes:
      - ../wordpress:/var/www/myapp
      - type: bind
        source: ./php/conf.d/xdebug.ini
        target: /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini 
      - type: bind
        source: ./php/conf.d/error_reporting.ini
        target: /usr/local/etc/php/conf.d/error_reporting.ini 
    depends_on:
      - mariadb

  mariadb:
    image: mariadb:10.4
    restart: always
    ports:
      - 127.0.0.1:3308:3306
    environment:
      - MYSQL_ROOT_PASSWORD=4321
      - MYSQL_DATABASE=wordpress
      - MYSQL_USER=wordpress
      - MYSQL_PASSWORD=1234
    volumes:
      - mariadb-data:/var/lib/mysql

  phpmyadmin:
    image: phpmyadmin/phpmyadmin:latest
    ports:
      - 8900:80
    environment:
      - PMA_ARBITRARY=1
      - PMA_HOST=mariadb
    depends_on:
      - mariadb

volumes:
  mariadb-data:

and my php-fpm dockerfile:

FROM php:7.4-fpm

RUN apt-get update && apt-get install -y 
    libicu-dev
    openssl 
    git 
    unzip
    nano
    && docker-php-ext-install 
    intl pdo pdo_mysql mysqli
    && docker-php-ext-enable 
    intl pdo pdo_mysql
RUN bash -c '[[ -n "$(pecl list | grep xdebug)" ]]
 || (pecl install xdebug && docker-php-ext-enable xdebug)'

2

Answers


  1. When starting the containers, you will need to instruct docker-compose to rebuilt the dockerfile.

    Try this:

    docker-compose up --build --force-recreate
    
    Login or Signup to reply.
  2. Discussion/Explanation

    What am i doing wrong?

    Perhaps it is a misunderstanding of the docker-compose.yml template, specifically in regards of the container for the php service (based on php:7.4-fpm) which might have been introduced in error.

    When you specify both the image and the build attribute of a service, the image as you build it will be stored under the image name (see also later References section).

    As you name the image as php:7.4-fpm and those build images are stored locally (there where you run docker-compose(1)) and you have in your Dockerfile within that build context that image same name php:7.4-fpm:

    FROM php:7.4-fpm
    # ...
    

    Then when you build for the first time, the image php:7.4-fpm is not available locally. Then it is build from Docker Hub fetched php:7.4-fpm and the build result is then overwriting the image php:7.4-fpm locally as you are using the same name (!).

    This is most likely not intended.

    This can also explain why --build --force-recreate does not work either: The Dockerfile build instructions consider php:7.4-fpm to be the image to be built from but it is already the result (of the first local build).

    Solution

    Remove the image service keyword. You don’t need it as you have the build keyword. Docker Compose will take care and name the image within your project automatically (based on service- and project name).

    services:
    
      php:
        build:
          context: ./php
        volumes:
          - ../.:/var/www/myapp:ro
    

    Then remove the dangling/tainted php:7.4-fpm image:

    $ docker image rm php:7.4-fpm
    

    These two steps should already solve your issue and get your docker composition up without errors.

    Additionally you can remove the workaround and do a plain pecl install xdebug && docker-php-ext-enable xdebug, here with better debugging abilities for the build (set -ex):

    FROM php:7.4-fpm
    
    RUN set -ex ;
        apt-get update ;
        apt-get install -y 
          libicu-dev
          openssl 
          git 
          unzip 
          nano 
        ;
        docker-php-ext-install intl pdo pdo_mysql mysqli ;
        docker-php-ext-enable intl pdo pdo_mysql ;
        :
    
    RUN set -ex ;
        pecl install xdebug ;
        docker-php-ext-enable xdebug ;
        :
    

    You could further tweak this by making the FROM image a build argument, bind it in the docker-composer.yml template (and use variables and defaults there-in, too). I’ll leave that to your liking.

    References

    If you specify image as well as build, then Compose names the built image with the webapp and optional tag specified in image:

    build: ./dir
    image: webapp:tag
    

    This results in an image named webapp and tagged tag, built from ./dir.

    From: https://docs.docker.com/compose/compose-file/compose-file-v3/#build

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search