I build 2 dockers, one docker with apache, one docker with php5, and I use docker-compose to start.
apache2 Dockerfile in directoy apache2:
FROM debian:latest
RUN apt-get update && apt-get install -y apache2
ADD test.php /var/www/html
CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]
and test.php:
<?php
phpinfo();
?>
php5 Dorckerfile in directory php:
FROM debian:latest
RUN apt-get update && apt-get install -y php5
docker-compose.yml:
apache:
build: ./apache2
container_name: apache
ports:
- "80:80"
links:
- "php5"
php5:
build: ./php
container_name: php
then I run:
docker-compose up
apache2 server start successfully. Then I access this server by http://server_ip, then I get index of debian.But when I access http://server_ip/test.php, just occur this:
<?php
phpinfo();
?>
php just doesn't work.And I don't why.
You can separate Apache and PHP with PHP-FPM. It is however that the DocumentRoot must be mounted on both containers.
Apache must be able to access the files locally (inside its container) as well as the PHP-FPM server.
I am currently working on the same, have a look at my docker-compose.yml here
https://github.com/cytopia/devilbox/blob/master/docker-compose.yml
Both volumes (in PHP and apache) are mounted to /shared/httpd
I would say its not possible to run seperate containers for php as apache module. I guess this is what Wolfgang meant.
If you want to seperate apache and php in two different containers you need to run php as fpm.
Have a look here for inspiration: How to correctly link php-fpm and Nginx Docker containers together?
If you need to run apache and php as apache_mod use a combined container like this: https://github.com/docker-library/php/blob/fec7f537f049aafd2102202519c3ca9cb9576707/5.5/apache/Dockerfile
from: https://hub.docker.com/_/php/
If you don't specifically need to separate Apache from PHP, then you might be good to go with an official php:5.6-apache image which comes with Apache out of the box.
For example, your docker-compose.yml might look something like this:
version: '3'
services:
web:
image: php:5.6-apache
ports:
- "8080:80" # Map container port 80 to host machine port 8080
volumes:
- ".:/var/www/html" # Mount current folder as volume to container at /var/www/html
Or, for a more real-life example, if you also need at least one of the following:
A custom web root (for Laravel, Symfony, etc)
Other Apache modules installed
Other PHP extensions installed
You might do something more like this:
version: '3'
services:
web:
build:
context: .
dockerfile: Dockerfile
ports:
- "8080:80" # Map container port 80 to host machine port 8080
environment:
APACHE_DOCUMENT_ROOT: "/var/www/yourapp.com/public"
volumes:
- ".:/var/www/yourapp.com" # Mount current folder as volume to container at /var/www/yourapp.com
And then your Dockerfile (which we reference from the docker-compose.yml above):
FROM php:5.6-apache
# Declare an environment variable with a default value for changing Apache's document root
# We will override this in docker-compose.yml
ENV APACHE_DOCUMENT_ROOT /var/www/html
# Configure web root
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf
# Install additional Apache modules
# This example: mod_rewrite & mod_headers
RUN a2enmod rewrite headers
# Install additional PHP extensions
# This example: memcached & mysqli
# For other extensions see official docs:
# https://hub.docker.com/_/php (section: How to install more PHP extensions)
RUN apt-get update && apt-get install -y libmemcached-dev zlib1g-dev \
&& pecl install memcached-2.2.0 \
&& docker-php-ext-enable memcached \
&& docker-php-ext-install -j$(nproc) mysqli
Related
I have to containerize a legacy PHP Laravel application and deploy it in an EKS cluster, and as I am completely new to both PHP and Laravel, I am currently having some difficulties.
After googling some examples of a Laravel Dockerfile, there seems to be many different methods of doing this and I had some trouble understanding and executing the process.
In one of the blogs I found, it seems to use a Dockerfile and a docker-compose.yaml file to containerize the application like the one used below.
FROM php:7.3-fpm
# step 2
WORKDIR /root
RUN apt-get update
RUN apt-get install -y curl
# step 3
RUN curl -sS https://getcomposer.org/installer | php
RUN mv composer.phar /usr/bin/composer
# step 4
RUN apt-get install -y zlib1g-dev && apt-get install -y libzip-dev
RUN docker-php-ext-install zip
# step 5
RUN composer global require laravel/installer
RUN ["/bin/bash", "-c", "echo PATH=$PATH:~/.composer/vendor/bin/ >> ~/.bashrc"]
RUN ["/bin/bash", "-c", "source ~/.bashrc"]
# step 6
EXPOSE 9000
CMD ["php-fpm"]
version: '3'
services:
proxy:
image: nginx:latest
ports:
- "80:80"
volumes:
- ./proxy/nginx.conf:/etc/nginx/nginx.conf
web:
image: nginx:latest
expose:
- "8080"
volumes:
- ./source:/source
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
php:
build:
context: .
dockerfile: php/Dockerfile
volumes:
- ./source:/source
I am guessing that the nginx is used for the web application server, kind of how Apache Tomcat is used in Spring Boot, but other than that, I am a little bit unclear on why there needs to be a yaml file for this.
In addition, I composed using the Docker and docker-compose.yaml file with the following command.
docker build -t website -f Dockerfile .
I did succeed in exporting the image, but I seem to have trouble running a container using this image.
It would be sincerely appreciate if you could tell me what I am doing wrong.
Thank you in advance!
Building with the Dockerfile only builds the php-fpm image, to run the container you should at least have one http server (like nginx) that forwards the requests to the php-fpm, there's probably something about that in ./proxy/nginx.conf,
It is also possible to build everything in 1 image (nginx, php-fpm), you probably want to start with something different then php:7.3-fpm (I usually start with alpine or ubuntu). Then its possible to run that image as a container and handle http requests.
I am trying to Dockerize my project (PHP MYSQL and PDO). Even though I added the scripts to install the extensions to my Dockerfile and every time I build it is installing them I am still getting: "Could not find driver". I checked in the phpinfo() and the driver is not there. I deleted all images and containers, built from scratch. Same result. Any ideas? In my docker file I have the following:
FROM php:7.4-apache
RUN apt-get update && apt-get upgrade -y
RUN docker-php-ext-install pdo pdo_mysql
EXPOSE 80
and my docker-compose.yaml file:
version: '3.3'
services:
web:
build:
context: ./php
dockerfile: Dockerfile
container_name: php74
depends_on:
- db
links:
- db
volumes:
- ./php:/var/www/html/
ports:
- 8008:80
db:
container_name: mysql8
command: --default-authentication-plugin=mysql_native_password
image: mysql:latest
restart: always
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: realDE
MYSQL_USER: khaldoun
MYSQL_PASSWORD: password
ports:
- 6033:3306
For the test I performed, I did the following:
Dockerfile -
FROM php:7.4-apache
RUN apt-get update && apt-get upgrade -y
RUN docker-php-ext-install pdo pdo_mysql
COPY $PWD/index.php /var/www/html
EXPOSE 80
# start Apache2 on image start
CMD ["/usr/sbin/apache2ctl","-DFOREGROUND"]
index.php
<?php
phpinfo();
?>
run command (I named the image pdo-test):
docker run --name=pdo-test -p 8080:80 -d pdo-test
Once the container was started I navigated to HTTP://localhost:8080/index.php and saw the PDO driver is loaded:
Please note the only difference between my Dockerfile and yours is that I copied a PHP page into /var/www/html and added a command that would start Apache when the container is run.
Things you should check:
is the volume you're mounting correct ./php:/var/www/html
since you have no command to execute Apache, confirm it is starting properly in the container. I tested both ways and it started each time, but you should bash into the container and make sure Apache is running as you expect.
EDIT I copied one of the php.ini files from the container
docker cp pdo-test:usr/local/etc/php/php.ini-production php.ini
and uncommented the PDO drivers:
;extension=openssl
;extension=pdo_firebird
extension=pdo_mysql
;extension=pdo_oci
;extension=pdo_odbc
extension=pdo_pgsql
;extension=pdo_sqlite
;extension=pgsql
Then I rebuilt the container, copying in the updated php.ini file:
FROM php:7.4-apache
RUN apt-get update && apt-get upgrade -y
RUN docker-php-ext-install pdo pdo_mysql
COPY $PWD/index.php /var/www/html
COPY $PWD/php.ini /usr/local/etc/php
EXPOSE 80
# start Apache2 on image start
# CMD ["/usr/sbin/apache2ctl","-DFOREGROUND"]
I can now see the php.ini file in phpinfo()
I'll preface this by saying I am very new to the docker world and despite reading documentation I am still a little confused about a few things.
I want to build a container with centos7 apache and php. I don't want to use an already existing image, want to build a custom container. I have the following folder structure
My rw/docker/webserver/Dockerfile:
FROM centos:7
ENV container docker
RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == \
systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*;
VOLUME [ "/sys/fs/cgroup" ]
CMD ["/usr/sbin/init"]
RUN yum -y install httpd
RUN systemctl start httpd
RUN systemctl enable httpd
RUN yum update -y && yum install -y libpng-dev curl libcurl4-openssl-dev
RUN docker-php-ext-install pdo pdo_mysql gd curl
RUN a2enmod rewrite
MY docker-compose.yml
version: '2'
services:
webserver:
build: ./docker/webserver
ports:
- "80:80"
- "443:443"
volumes:
- /**PATH**/rw/services:/var/www/html
links:
- db
db:
image: mysql:5.7
ports:
- "3306:3306"
volumes:
- ./db:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=****
- MYSQL_DATABASE=****
This fails when docker tries to start httpd with the error
ERROR: Service 'webserver' failed to build: The command '/bin/sh -c systemctl start httpd' returned a non-zero code: 1
Q1. Why is the install failing?
Q2. Is the the proper way to do this? Should my dockerfile for centos and apache+php be separate. If yes, how does that work?
Q1. I think systemctl may not be provided with CentOS docker image.
Indeed, docker services are not meant to be run as daemons, but in the foreground. Take a look at apache's original http-foreground shell script for a better understanding of the concept.
Q2. Not that's not the right way IMHO.
Running apache is the job of an entrypoint or command script.
So instead of RUN your-command-to-run-apache, it would rather be CMD your-command-to-run-apache.
Once again, Apache official repository can give you some clue about this.
To my eyes these kinds of Dockerfiles look too old as they try to map the external docker daemon inside the container. That's a workaround as a systemd daemon cannot be run separately in a container.
Instead I am using the docker-systemctl-replacement script. The docker systemctl.py can parse the normal *.service files to know how to start and stop services. You can register it as the CMD of an image in which case it will look for all the systemctl-enabled services - those will be started and stopped in the correct order.
There are even some testcases for the LAMP stack available, so it should work in your case quite smoothly. The systemctl.py script is compatible with the systemd systemctl as much as that one simply overwrite the /usr/bin/systemctl inside the image - and all the non-docker installation instructions will work for docker builds.
Let's say I have the following situation:
docker-compose.yml
version: '3'
services:
web:
build: .
links:
- apache
- php
- node
depends_on:
- apache
- php
- node
volumes:
- .:/var/www/html
apache:
image: httpd
php:
image: php
node:
image: node
and I also have a Dockerfile
FROM phusion/baseimage
RUN apt-get update
RUN apt-get install -yq git curl zip wget curl
RUN curl -s https://getcomposer.org/installer | php # error, no PHP exec found
RUN mv composer.phar /usr/local/bin/composer
RUN npm install -g bower gulp
COPY ./ /var/www/html
WORKDIR /var/www/html
RUN apt-get clean
RUN rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
CMD ["/sbin/my_init"]
Now my question is: how could I use PHP & Node, which are installed in separate containers, in this main app Dockerfile? Is that even possible, or do I need to manually install PHP & Node inside my Dockerfile?
Docker doesn't work the way you are thinking. This isn't like code inheritance or configuring a single machine with multiple runtime languages. You are configuring multiple virtual machines, each with their own runtime environment.
if you want to run a PHP app, you put that app in the container that has PHP. same with Node.
I'm creating a Symfony environment (PHP-FPM, Nginx, & more) with Docker & Docker-compose.
But, PHP does not use my php.ini and ignores the config (date.timezone parameter is not found in my Symfony application).
Of course, when I go on my container, the date.timezone is correctly set in the 2 php.ini (cli & FPM).
I don't understand why, but it works if I put my php.ini in /usr/local/etc/php/ folder (wtf)
Did I miss something?
docker-compose.yml :
nginx:
image: nginx
volumes:
- "./docker/nginx/nginx.conf:/etc/nginx/nginx.conf:ro"
links:
- "php:php"
ports:
- "80:80"
- "443:443"
working_dir: "/etc/nginx"
php:
build: docker/php
volumes:
- ".:/var/www:rw"
working_dir: "/var/www"
Dockerfile :
FROM php:5-fpm
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && \
apt-get install -y php5-common php5-fpm php5-cli php5-mysql php5-apcu php5-intl php5-imagick && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
RUN sed -i 's/;date.timezone =/date.timezone = "Europe\/Paris"/g' /etc/php5/fpm/php.ini
RUN sed -i 's/;date.timezone =/date.timezone = "Europe\/Paris"/g' /etc/php5/cli/php.ini
RUN usermod -u 1000 www-data
Official PHP Docker Image use /usr/local/etc/php as base folder: see Dockerfile.
I've been facing the same problem for a while, the host machine had a correct date/time but every php container was in GMT instead of Europe/Paris or host date time.
For those of you who will search for a valid answer and need more precisions than #moliver answer, using sed in the dockerfile maybe not the best answer. Moreover, php.ini might not be created at building time. Here is the ls of /usr/local/etc/php in one of my php container.
root#6fd7bc929a7e:/usr/local/etc/php/conf.d# ls
docker-php-ext-bcmath.ini docker-php-ext-exif.ini docker-php-ext-mysqli.ini docker-php-ext-soap.ini docker-php-ext-xsl.ini
docker-php-ext-bz2.ini docker-php-ext-gd.ini docker-php-ext-pcntl.ini docker-php-ext-tidy.ini docker-php-ext-zip.ini
docker-php-ext-calendar.ini docker-php-ext-mcrypt.ini docker-php-ext-pdo_mysql.ini docker-php-ext-xmlrpc.ini ext-imagick.ini
(yes i added a lot of extensions, but no php.ini by default).
docker-compose is very flexible, you can add a volume containing php.ini info :
version: '2'
services:
php:
build: ./DOCKERFILES/phpdemo
container_name: applicationDEMO
volumes:
- "./conf/whatever.ini:/usr/local/etc/php/conf.d/whatever.ini"
- "/etc/timezone:/etc/timezone:ro"
- "/etc/localtime:/etc/localtime:ro"
And in your ./conf/whatever.ini
date.timezone = "Europe/Paris"
Hope this helps
I had this issue in my php:5.6-apache docker image.
I simply added these two lines in my dockerfile:
# use development php ini
RUN mv /usr/local/etc/php/php.ini-development /usr/local/etc/php/php.ini
# set default timezone
RUN sed -ri -e 's!;date.timezone =!date.timezone = "Europe/Paris"!g' /usr/local/etc/php/php.ini
It worked well. :-)