Working with a Docker file which includes PHP, Apache, and MySQL. I was able to get the page to pull up in localhost. However, I am unable to get the MySQL running.
# Use an official PHP Apache runtime as a parent image
FROM php:7.0-apache
# Set the working directory to /var/www/html/
WORKDIR /var/www/html/
# Install mysqli extensions
RUN docker-php-ext-install mysqli && \
apt-get update && \
apt-get install -y zlib1g-dev && \
apt-get install -y libxml2-dev && \
docker-php-ext-install zip && \
docker-php-ext-install xml
# Make port 80 available to the world outside this container
EXPOSE 80
Based on the above, when I attempt to run the following command:
docker run --name some-mysql -e MYSQL_abcd_123456=my-secret-pw -d mysql:tag
I receive the following error in the terminal:
Unable to find image 'mysql:tag' locally
docker: Error response from daemon: manifest for mysql:tag not found.
What am I missing?
docker run command requires the image name parameter with optional version of the image (recommended).
Use:
docker run --name some-mysql -e MYSQL_abcd_123456=my-secret-pw -d mysql:latest
to pull the latest mysql image or choose the exact version listed by supported tags
for example:
5.7.25
or
8.0.15
In majority cases you should not use the tag with the version latest (or skip the version) because that is ambiguous and can give you different versions of the image on two different machines even they used for the build the same Dockerfile FROM statement or you used the same docker run (docker pull) command. Read more
I would recommend always stick to the explicit version number if possible, for example:
docker run --name some-mysql -e MYSQL_abcd_123456=my-secret-pw -d mysql:8.0.15
Related
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.
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.
I have two Docker images created on different days. One is able to connect with a separate mysql 8.0 image, the other is not.
The history of the images is that I made one that works, tweaked the Dockerfile for portability, then when that image didn't work, I rolled the Dockerfile back to the original - but it still didn't work. I added the --no-cache option to the build but that didn't help.
The details:
Here is the Dockerfile:
FROM php:7.2-apache
RUN apt-get update && apt-get install -y \
apt-utils \
zlib1g-dev \
libmemcached-dev \
memcached \
libevent-dev \
libc-client-dev \
curl \
libxml2-dev \
zip \
unzip \
ldap-utils \
&& docker-php-ext-install mysqli pdo_mysql \
&& pecl install memcached xdebug \
&& docker-php-ext-enable memcached xdebug
RUN service memcached restart
Here's the line in the php that works for one image and not the other:
mysqli_connect('mysql80', 'my_username', 'my_password', 'my_database');
The error is:
Message: mysqli_connect(): php_network_getaddresses: getaddrinfo failed: Name or service not known
However, when I run the following from the command line of EITHER running container, it works just fine:
mysql --host=mysql80 -umy_username -pmy_password
I run the containers with identical instructions except the port to listen on, and I connect them to the network with scripts that are identical except for the image name.
Other things I've checked in running instances of the two images:
php -i yields identical results except of course HOSTNAME
likewise, phpinfo() in the code produces the same results except ports and HOSTNAME.
apache2ctl -M is identical between the two
apt list --installed lists identical packages
I currently have them attached to the same bridge network, communicating with the same mysql instance.
They are running php code from the same mounted source directory (confirmed by altering the code).
For completeness, here's how I run the two images (Usually of course I would only run one at a time, but having both running does not change the behavior.)
# newer image that doesn't work
docker run -d -p 8787:80 --name awesomeApp \
-v /path/to/php/src:/var/www/html \
-e DB_HOST='mysql80' \
awesomeImage:latest
docker network connect awesome-net awesomeApp
# old image that does work
docker run -d -p 8788:80 --name oldAwesome \
-v /path/to/php/src:/var/www/html \
-e DB_HOST='mysql80' \
awesomeImage:oldOneThatWorks
docker network connect awesome-net oldAwesome
I've completely run out of things to try to find a meaningful difference between the images, and need to be able to modify the image and have it work. Any suggestions welcome.
I've created a docker container using https://hub.docker.com/_/php/.
I need to connect from this container to another container running postgres (https://hub.docker.com/_/postgres/). However, I can't seem to get the PHP 7 PDO drivers for postgres to install properly.
Here's what my Dockerfile looks like:
FROM php:7.0-cli
COPY ./app /app
WORKDIR /app
RUN apt-get update && apt-get install -y \
postgresql-client \
&& docker-php-ext-install -j$(nproc) pgsql
CMD [ "php", "./do_stuff.php" ]
in place of pgsql I've tried pdo-pgsql, php7.0-pgsql, and tried adding a line to add the ppa:ondrej/php repo to pull from with no luck.
Most of the packages fail to install (even pdo-pgsql which was suggested by docker after failing to find php7.0-pgsql), but the odd one that does install still throws an error that the drivers aren't found when trying to create a PDO connection.
Is there a right way to get the PDO drivers for postgres installed in a docker container?
Ensure the extension is symlinked in /etc/php/7/cli/conf.d or /etc/php/7/fpm/conf.d - folders depend on your distribution.
You can find out if the module is loaded by running
php -m
php7-fpm -m
if the module is missing, check /etc/php/7/modules if the .ini file is present there and symlink it, then the module should get loaded.
I want to run my Symfony3 app out of Docker container. As I understand I can install/create multiple images with docker and spin them up into a container that will hold my app.
I been going through some docks on Docker on how I may do this, I seen that I can have a docker images such as:
Ubuntu
PHP
Nginx -> As I understand it is like an Apache server, so in theory it will handle all the requests and responses.
But I still find it hard to understand the concept of spinning multiple images into one container.
Also I have seen something called DockerFile which apparently can can build a my dev environment into one container that I can also work with.
Question 1:
Can someone please clarify the whole process I still find it hard to wrap my head around it.
Question 2:
How can I build DockerFile and what is it?
You don't want to spin multiple images into one container. It's possible that you don't even need a docker file (but for PHP, you probably do).
The usual mantra concerning docker is "one process per container", and after working with it for several months, I find this to be great advice, even if it's not always achievable. For a PHP app, whether it's symphony, Cake, Laravel, Wordpress, whatever, this is how I do it. I use apache, and it sounds like you might be more familiar with apache as well. You can easily substitute the official nginx container with minor changes to my example if desired.
One container runs PHP-FPM
One container runs Apache (httpd)
If you need a database, one container for mysql
Optionally, a container for composer.
docker-compose to orchestrate all of these containers
I typically use the official httpd container, the official mysql container, and I extent the offical php fpm container as described to include the mods that I need. Here is an example of a PHP-FPM dockerfile that adds in some external libs that might be needed for your app:
FROM php:5.5-fpm
RUN apt-get update && apt-get install -y \
php5-mysql \
php5-curl \
php5-common \
php5-gd \
php5-imagick \
php5-intl \
php5-dev \
php5-sqlite \
php5-xdebug \
php5-memcached \
\
libmemcached-dev \
libmcrypt-dev \
libfreetype6-dev \
libxml2-dev \
libmagickwand-dev \
libjpeg62-turbo-dev \
libpng-dev && \
\
docker-php-ext-install pdo pdo_mysql && \
docker-php-ext-install soap && \
docker-php-ext-configure gd --with-jpeg-dir=/usr/include/ && \
docker-php-ext-install gd && \
docker-php-ext-install iconv mcrypt && \
\
pecl install imagick && \
docker-php-ext-enable imagick && \
pecl install memcached && \
docker-php-ext-enable memcached && \
\
pecl install xdebug && \
docker-php-ext-enable xdebug && \
\
mkdir -p /app/content && \
mkdir -p /app/usr/local/apache2 && \
cd /app/usr/local/apache2 && \
ln -s ../../../content htdocs
COPY copy/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini
This builds an image that I actually use for development. In addition to installing dependencies, it copies a config for xdebug, and sets up the folder structure to hold my app.
You would build this container like this:
docker build -f nameoffile.Dockerfile -t myhubaccount/myphpcontainer \
./path/to/folder/where/dockerfile/is
This builds an image on your machine tagged as myhubaccount/myphpcontainer and you can refer to it in your compose file.
A basic compose file that tells these containers how to talk to each other might look something like this:
docker-compose.yml
version: '2'
services:
httpd:
image: httpd:latest
volumes:
- ./docker_conf/httpd.conf:/usr/local/apache2/conf/httpd.conf
- ./webroot:/usr/local/apache2/htdocs
ports:
- "80:80"
links:
- fpm
logging:
options:
max-size: "0"
database:
image: mysql
ports:
- "3306:3306"
volumes:
- ./schema.sql:/docker-entrypoint-initdb.d/schema.sql
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
MYSQL_DATABASE: development
logging:
options:
max-size: "5k"
fpm:
image: myhubaccount/myphpcontainer
volumes:
- ./webroot:/app/content
links:
- database
logging:
options:
max-size: "50k"
I think it's beneficial to highlight several parts of this file. First, for php-fpm you need to set up apache to talk to the fpm server. The links object under httpd tells the container that there is another container with a domain name of "fpm", and docker knows how to resolve that name, so any communication with the fpm server can use that name. We have to mount (under volumes) the apache config in the httpd container. It looks like the default config, but has this part added to accommodate php-fpm:
ProxyTimeout 30
<FilesMatch ".*\.php$">
SetHandler "proxy:fcgi://fpm:9000"
</FilesMatch>
This tells apache to forward requests for php files to the fpm server and serve the result.
The ports entry causes port 80 of the container to be forwarded to port 80 of the docker machine. This is localhost on linux, or the docker-machine ip on Mac and Windows. You can find this ip with the console command docker-machine ip.
We do the same thing on the mysql container so that we access mysql directly with a tool like Mysql Workbench. You can read about the environment variables that the official mysql container allows and what they do.
We have links for fpm, if it needs to talk to the database. The hostname for your database in this case is just "database".
The logging items are not necessary, just personal preference to keep the log output from becoming excessive.
Once you have all this in place, you bring up the environment with docker-compose up. If you want to take a look at what a container looks like you can get a shell on a running container with docker-compose exec fpm bash, substituting "fpm" with the name of the container you want to look at. The caveat here is that the container must actually include the bash binary. All of these here do, but some containers do not.
I hope that this gives enough php-specific example to help you wrap your head around how docker sort of works. I would suggest re-reading the docs for bother Docker and Docker Compose. And I would also suggest reading the Dockerfiles for the official images if you are interested in building your own containers. The docs have links to Dockerfiles that the Docker team considers to be exemplary.