Install mongodb driver in docker with dockerfile - php

I have a mongodb docker container. I need another docker container which will have php and apache installed. I want to run a php script from this container and send some data to the mongodb container to save the data in mongodb database. So i need to install mongodb driver in the php-apache container.
To do that, i have created following dockerfile:
FROM php:7.3-apache
COPY src/ /var/www/html
RUN apt-get update
RUN apt-get install openssl libssl-dev libcurl4-openssl-dev
RUN pecl install mongodb
RUN cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini
RUN echo "extension=mongodb.so" > /usr/local/etc/php/php.ini
EXPOSE 80
It first builds php-apache docker image. Then it should install mongodb driver.
But when i run the following command
docker build -t my-mongo .
At one point it shows following message and stops the execution:
Need to get 2213 kB of archives.
After this operation, 9593 kB of additional disk space will be used.
Do you want to continue? [Y/n] Abort.
The command '/bin/sh -c apt-get install openssl libssl-dev libcurl4-openssl-dev' returned a non-zero code: 1
What went wrong here? Is there anything wrong in the dockerfile ?

What went wrong here? Is there anything wrong in the dockerfile ?
There are at least three things wrong with your Dockerfile IMO.
The first one is not in direct relation to your problem, but you are creating way too many layers (one for each RUN command) for something as simple as adding a driver to your image. You should put all this in a single layer (i.e. a single RUN command) and cleanup after yourself at the end to keep the layer footprint small.
Now the core of your real problem. As you can see in your output, apt-get is launched in interactive mode and asks for a confirmation. The docker build process can't handle that and therefore aborts the command causing the build to fail. To overcome this, apt-get has a -y option to answer 'yes' to all prompts by default.
The last one is in the line where you add the mongo driver to php.ini: you are redirecting echo output to your file with a single gt; sign (>), hence you are replacing the full content of the file you just copied. You must use a double gt; sign (>>) for content to be appended.
The following Dockerfile should fix the problems above (tested without the copy of sources + cp of your own php.ini file since I don't have them)
FROM php:7.3-apache
COPY src/ /var/www/html
RUN apt-get update \
&& apt-get install -y --no-install-recommends openssl libssl-dev libcurl4-openssl-dev \
&& pecl install mongodb \
&& cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini \
&& echo "extension=mongodb.so" >> /usr/local/etc/php/php.ini \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
EXPOSE 80
Some explanation:
The && notation allows to run all commands one after the other in a single docker RUN command resulting in a single intermediate container, thus a single layer.
-y --no-install-recommends options to apt-get ask apt to not go interactive (answer yes everywhere) and to install only needed packages, not the recommended ones.
The two last instruction apt-get cleann && rm -rf /var/lib/apt/lists/* remove all caches made by running apt so that the layer stays as small as possible. (see apt-get chapter in docker best practice)

put this at the beginning of your Docker file, it is important to have it before installing all other extensions, otherwise it fails.
FROM php:7.3-apache
RUN apt-get update -y && apt-get upgrade \
&& pecl install mongodb && docker-php-ext-enable mongodb
That's all what I needed to get mongodb running FROM php:7.3-cli-buster Probably it will work for other versions - fpm, apache etc as well.

Related

Moving a PHP Laradock project to Mac M1

I need to be able to develop an old Laradock project on my new M1. So far, I have nearly everything up and running. The one holdout that I have is HHVM. HHVM doesn't support M1 in any way, so I need to move the project away from it. I get this when attempting to start docker with HHVM:
failed to solve: executor failed running [/bin/sh -c apt-get update -y && apt-get install -y software-properties-common wget && wget -O - http://dl.hhvm.com/conf/hhvm.gpg.key | sudo apt-key add - && add-apt-repository "deb http://dl.hhvm.com/ubuntu $(lsb_release -sc) main" && apt-get update -y && apt-get install -y hhvm && apt-get clean && rm -rf /var/lib/apt/lists/*]: exit code: 100
I suspect I need to replace HHVM's functionality with PHP-FPM. I'm a little stumped on where to go with it, though. I was not the one that initially built this program, and PHP isn't my forte. I have a hard time finding anything online about this issue, though I'd imagine people have to have encountered it since M1 has come along.
If I comment out HHVM in laradock, docker-compose.yml then I can get everything else to build - I also get 500s when attempting to access the project.
I'm not sure where to even go with this issue.

Docker with laravel fails because of php extension

Running Laravel on an appache server.
Upon building the image with docker-compose up --build with the following Dockerfile
FROM php:7.3-apache-stretch
RUN apt-get update -y && apt-get install -y libpng-dev
RUN docker-php-ext-install pdo pdo_mysql gd
FROM composer:1.9.0 as build
WORKDIR /app
COPY . /app
RUN composer global require hirak/prestissimo && composer install
I am getting the error message:
phpoffice/phpspreadsheet 1.13.0 requires ext-gd * -> the requested PHP extension gd is missing from your system.
This happens when the composer install command runs.
As you can see up, I am actually installing gd from php, so it should not give me this error message.
Do you have any idea how I can solve it?
Thanks!
It's happen, because you are using multistage building and your composer second stage have nothing to do with previous build using PHP container. Primary use case with multistaging is to produce some useful artefacts which can be used later.
So what I suggest is to copy composer file from composer image, then place it somewhere in your php container.
I will give you my solution which is working perfectly for me with laravel/symfony etc.
FROM php:7.4.4-fpm
# We copy composer from it's original image to our php container to use it later.
COPY --from=composer:1.9 /usr/bin/composer /usr/bin/composer
WORKDIR /var/www
ARG USER_ID
RUN useradd -s /bin/bash -d /home/user/ -m -G sudo,www-data user -u $USER_ID
RUN apt update && apt install -y zip unzip wget zlib1g-dev libicu-dev
RUN docker-php-ext-install pdo_mysql intl opcache gd
USER user
RUN wget https://get.symfony.com/cli/installer -O - | bash
ENV PATH="/home/user/.symfony/bin:${PATH}"
COPY php.ini /usr/local/etc/php
# You can also run here composer install, depends on your use case
You can change your docker image. For example try this:
FROM richarvey/nginx-php-fpm
WORKDIR /app
RUN php ./artisan config:cache && composer install

How can I store composer cache in a volume during when building a docker?

I am using this Dockerfile to create an image with my PHP application dependencies:
FROM composer:latest AS composer
COPY ./ ./
VOLUME composer-cache:/tmp/
RUN composer install
FROM php:7.1-fpm
WORKDIR /app
RUN apt-get update && \
apt-get install -y libpq5 libpq-dev libmemcached11 libmemcached-dev libmagickwand-6.q16-6 libmagickwand-dev unzip --no-install-recommends && \
docker-php-ext-install pdo pdo_pgsql && \
pecl install imagick && \
echo extension=imagick.so >> /usr/local/etc/php/conf.d/imagick.ini && \
apt-get remove -y libpq-dev libmemcached-dev libmagickwand-dev && \
apt-get autoremove -y && \
apt-get autoclean -y
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
COPY ./ ./
COPY --from=composer /app/vendor ./vendor
For faster build and reducing network activity I want to store composer's cache in the volume called composer-cache. But composer does not store anything data in that volume.
I checked a official composer Dockerfile and noticed it's exports COMPOSER_HOME environment variable points to /tmp directory. I think is enough to store cache outside from container, but this is not.
On every build composer downloads all dependencies again, and the volume remains empty.
Your problem is that the directive VOLUME creates a volume mountpoint to be used at runtime.
That volume is actually created when you execute docker run. During build time (docker build), that instruction has no effect.
But you can use new build time enhancements added for this kind of thing.
You need to add the following to your Dockerfile:
# syntax=docker/dockerfile:experimental
FROM composer:latest AS composer
COPY composer.json composer.lock ./
RUN --mount=type=cache,target=/tmp/cache composer install --prefer-dist --no-suggest
### your next build stage...
This will result in speedier install execution after the first time.
To gain download speed (which may make the above kinda relatively moot), you can use Prestssimo. This is a composer plugin that makes that composer download are performed in parallel instead of sequentially.
(Note, with Composer 2 Prestissimo is obsolete, since composer itself performs this type of download optimisation).
You'd end up with
# syntax=docker/dockerfile:experimental
FROM composer:latest AS composer
RUN composer global require hirak/prestissimo
COPY composer.json composer.lock ./
RUN --mount=type=cache,target=/tmp/cache composer install --prefer-dist --no-suggest
### your next build stage...
You would then call your build process like this:
DOCKER_BUILDKIT=1 docker build .
It is not currently possible to use docker-compose to enable buildkit. But with a bit of foreplanning you can build your images first, and declare those images in your docker-compose files for orchestration.
I find that simply using Prestissimo is enough as not to need additional cache layers, but you'll need to check what's best for your scenario.

Where to store the docker-php-ext files?

I have set up a Symfony4 project with in a Docker container.
I followed the Jobeet-Tutorial where they use the phpdocker.io - generator.
All works perfect but very slow. So I want to speed up and enable the opcache and configure it.
I found helpful links in the net. So I added to my Dockerfile this:
RUN docker-php-ext-configure opcache --enable-opcache \
&& docker-php-ext-install opcache
# Copy configuration
COPY config/opcache.ini $PHP_INI_DIR/conf.d/
The problem is that I don't have this helperscripts:
docker-php-ext-configure
docker-php-ext-install
docker-php-ext-enable
So I decided to search it in the internet and copy it into my project.
Now I have it in the php-fpm folder of my docker directory.
My directory looks like this now - the scripts are in the beneath the Dockerfile:
Is there any other step I forgot to do, like registering these scripts somewhere?
The most immediate answer to your question is that you need to copy those scripts into the Docker image you are building. To do that, you should create a subdirectory within the php-fpm directory named bin and put all of those scripts in that directory. Then, in your Dockerfile:
COPY bin /usr/local/bin
Now when you try to use that image, the scripts will be within your executable PATH.
However
Those docker-php-ext-* scripts you found are from the PHP project's official Docker images and are intended to be used with those images.
You are using the phpdockerio/php73-fpm:latest image, which seems to use ubuntu:bionic as a base image. These scripts depend heavily on the PHP Dockerfiles, which do a bunch of preparatory steps, such as downloading the source code for the PHP interpreter itself to /usr/src. Making these scripts run directly in a phpdockerio container would be a very involved process.
That leaves you with 2 options:
Forgo the scripts and install Ubuntu's prebuilt packages. You seem to already have the apcu, apcu-bc, cli, curl, json, mbstring, opcache, readline, xml, and zip PHP extensions installed. You can see the full list of packages that are available from the default repos this way by running
docker run --rm -it phpdockerio/php73-fpm:latest bash -c 'apt-get update && apt search ^php7.3-';
When you know which packages you want, you can add them to your Dockerfile.
Switch to using an official PHP image instead so you can use the docker-php-ext-* scripts. The phpdocker-io image you are using is essentially PHP7.3-FPM on Ubuntu, and the closest official PHP image to that is php:7.3-fpm-stretch (Debian 9). You can build and install the extensions listed in Option 1 by changing your PHP-FPM Dockerfile to:
FROM php:7.3-fpm-stretch
# Run in Bash instead of Bourne shell to get lists
RUN ["bash", "-c", " \
#Exits on error or unbound variable. Now we can use semicolons instead of
#ampersands
set -eu; \
\
ext_build_dependencies=( \
#Needed to build php-curl
libcurl4-gnutls-dev \
\
#Needed to build php-mbstring
libedit-dev \
\
#Needed to build php-xml \
libxml2-dev \
\
#Needed to build php-zip
zlib1g-dev libzip-dev \
); \
\
apt-get update; \
apt-get install -y ${ext_build_dependencies[#]}; \
\
#Build the extensions
docker-php-ext-install curl json mbstring readline xml zip ; \
pecl install apcu apcu_bc; \
\
apt-get purge -y ${ext_build_dependencies[#]}; \
apt-get autoremove -y; \
apt-get clean -y; \
"]
If Ubuntu 18 and Debian were binary-compatible (they're not), you could try a third option, which would be building the extensions using a PHP image, then copying over the built extensions as the second stage of a multi-stage build. This would be possible if your image uses the same Linux flavor as as the PHP image does. For example, if your image were based on alpine:3.8, you could use php:7.3-fpm-alpine3.8 to build your extensions and copy them over.

Docker and symfony

I'm struggling with Docker.
I'm tring to create an image to work on symfony project and to learn Docker in the same time.
Here is my Dockerfile:
FROM php:7-apache
LABEL Description = "This image is used to start Symfony3 project"
ENV DIRPATH /var/www/html
# apt-get command
RUN apt-get update && apt-get install -y \
vim \
git \
&& apt-get clean
# Install Composer
RUN curl -sS https://getcomposer.org/installer | php
RUN mv composer.phar /usr/local/bin/composer
# Install the Symfony Installer
RUN curl -LsS http://symfony.com/installer -o /usr/local/bin/symfony
RUN chmod a+x /usr/local/bin/symfony
I build the image with the command:
docker build -t symfony .
Works well! Cool!
I'm create a container with:
docker run --name symfony -d -v "$PWD":/var/www/html -p 80:80 symfony
Works well also. The web server is running on the good port.
I can go in my container with:
docker exec -ti symfony bash
But when I'm trying to do a composer update, I have some errors:
Failed to download symfony/symfony from dist: Could not decompress the archive, enable the PHP zip extension.
A php.ini file does not exist. You will have to create one.
How can I create the php.ini in Dockerfile?
I also think that I have an issue with permission.
When I'm trying to the web/app_dev.php I have this message:
You are not allowed to access this file. Check app_dev.php for more information.
You can ADD a custom php.ini configuration specifing it in the dockerfile,
As Example, you can take a look at this repo for this example:
dokerfile
# install a few more PHP extensions
RUN apt-get update && apt-get install -y php5-imagick php5-gd php5-mongo php5-curl php5-mcrypt php5-intl
# copy a custom config file from the directory where this Dockerfile resides to the image
COPY php.ini /etc/php5/fpm/php.ini
You can find various approach and various sample on the net.
Hope this help
Next to the missing php.ini file you should also install zip so you can download from dist, i.e.
RUN docker-php-ext-install zip
Which will install and enable the PHP zip extension which is requested in your error message.

Categories