Home > other >  Docker-Compose, Dockerfile and Build Image Problems (php-fpm pecl xdebug)
Docker-Compose, Dockerfile and Build Image Problems (php-fpm pecl xdebug)

Time:06-20

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)'

CodePudding user response:

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

CodePudding user response:

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

Try this:

docker-compose up --build --force-recreate
  • Related