Container exists immediate when adding mysqli to php container

I’m new to docker and trying to stand up a php/mysql environment on my Docker Desktop for Windows. I got the basics working right away. I can serve up a php page, and I can connect to the database from heidisql on my desktop. The problem comes when trying to use the database from php, it complains that there is no mysql module I’m trying to call. I realized that I needed to add mysql support to the php container and I got that to work with this dockerfile:

FROM php:7.2-apache
RUN docker-php-ext-install pdo pdo_mysql mysqli
COPY . /var/www/html/
EXPOSE 80/tcp

When I run this dockerfile and serve up my php file that tries to connect to mysql, I get an error that it can’t find the database server. However when I add this to my docker-compose.yml the php container exists immediately. Here is my yml file:

version: "3.8"

    image: php:7.2-apache
    command: docker-php-ext-install pdo pdo_mysql mysqli
      - 80:80
      - ./:/var/www/html/
      - MYSQL_HOST
      - MYSQL_USER
      - MYSQL_DB
    image: mysql:5.7
      - 33065:3306
      - devphp-mysql-data:/var/lib/mysql


If I take the command line out, everything works fine. Except for the minor fact that php is missing the mysql module.
BTW the exit code is 0 and I see nothing in the log that points to an issue. It’s just like compose file is configured to just install the mysql module and exit.
What am I doing wrong?

Not sticking to your self build image - it is way cleaner than what you try to do in your compose file.

Depending wether the original image uses ENTRYPOINT or CMD to start the entrypoint script, you command either becommes an arguement to ENTYPOINT or completly replaces CMD. Some entrypoint scripts just “exec @$” and do not do further processing.

Thus said: it looks like your command replaces/eclipses the entrypoint script, so that your php container starts, performs your command and then exits the container because no foreground process is running.

the image uses:

ENTRYPOINT ["docker-php-entrypoint"]
CMD ["php-fpm"]

Your “command:” replaces php-fpm, which apperently is what makes php-fpm fly :smiley:
Also are you sure about port 80? the original image exposes port 9000.

OK so how do I fix it. I’m not trying to doing something novel, I’m just stumbling around trying to figure Docker out, and based on what I’ve read so far led me to do things this way. If you could guide me on the right way to accomplish this, I would really appreciate it. What do you mean by my self build image? What is a good resource to understand the difference between entrypoint and cmd? I know nothing about this php image I found on Docker Hub.


Since we both would need to google for that, I leave it to you. The first hit should be viable, as the topic realy is not complicated.

Generaly I would advise to study this free self-paced training: Introduction to Containers. It will provide a solid foundation and gives examples on how to do things (it will also cover ENTRYPOINT and CMD). Make sure to do the hands-on exercersices. Docker makes more fun, If you have a solid foundation and don’t have to spend time fighting the problem of the minute.

Then you need to solve that. You can ignore error messages temporarily and try an other solution when you just try to understand what you are dealing with, but always go back to the first idea because usually that is the better idea.

If the error message says PHP cannot find the database, than it is probably right and your database configuration or network is wrong. If you don’t understand the error message, share the exact error message, because that is how we can help. And share how you tried to access the database too. If the error message is really about the database and not the database server, then your network is good and the connection was established but your database name is wrong or that database does not exist and you can start to find out why which is an other problem.

You saw the Dockerfile of the PHP-FPM variant, but the one that @siggib007 is the apache variant which is Apache HTTPD server with PHP as a module. PHP FPM would listen on port 9000 this will listen on port 80.

However, port 80 is exposed in the official image, so that extra EXPOSE 80/tcp will not do much. And as we know, and everyone should now, it is not necessary for making that port available.

The best source is yourself. :slight_smile: I like the most in Docker that we can play with it learn without damaging our machine (well, let’s say it is harder to damage). You can read about it and you will think it is clear and you understand finally, and a year later you realize you didn’t really understand. So I played with it:

Try the dockerfiles and inspect the built image to see the resulted commands. You can use the scripts I created to create a more structured output showing which docker build will give you wich final command in the container. If you want to see it in action, watch the video I linked in the README. It is a Hungarian video, but you just need to watch the screen in English.

The best way though is to try it yourself so you can copy the docker commands from the screen if you don’t want to run my script…

I seemed to have phrased my question very poorly, apologies for that.
Yes, I mentioned the error about the database to indicate that I knew that it was saying it couldn’t reach the mysql server which wasn’t running because I was running the standalone php server, the point there was that it proved the server successfully loaded the mysql module. And when I ran the compose without the command the error was indicating that the module wasn’t loaded. It apparently was a failed attempt at demonstrating that I had done some level of investigation, including web search, to try to find the answer and wasn’t just posting because I was too lazy to troubleshoot myself. Again sorry my poor phrasing caused the wrong impression.
What I was really trying to ask is if it was possible to run the install command and httpd in the command, does that make sense. I’m afraid my Linux foo isn’t strong enough to get that to work and Google isn’t of much to me here.
I’m gathering from the replies that I should be referencing my own image and not the standard image with install command. Also good to know that the port command is not needed.
If I may ask a best practices question. In cases like this, is it better to compile your own image and then call that in your compose script, or is it best practice to reference the standard image and modify it on the fly in the compose script? Or does it not matter?

Also thanks for the links to the slides and the script, I’ll check those out.

Good catch! I mixed it in my head with what I saw in this thread, which used an fpm based image.

It is best practice to have everything required available in the image. It is high likely that an image with mysqli/php does already exist on dockerhub. Though, depending on the reputation (downloads/stars) of such image(s) it might be still more usefull to build your own custom image:

The custom image approach will be self contained as everything required to run your application will comme with the image vs. the approch where you install package during the start of the container (which by the way will be executed whenever the container is started), which introduces external runtime dependencies to a repository that might be not always available or packages get removed (which with the mysqli package is highly unlickely I guess).

Generaly an image should contain the core service, all its dependencies and a usefull base configuration to run a container based from it. Idealy the image has a clever entrypoint script to override settings in the configurations OR at least allows to mount existing configs into the container.

I am sure you already know this: a container is supposed to be ephemeral and persistant data is supposed to be stored in volumes to be persisted outside the container.

1 Like

Thank you, that was a very informative and helpful response.

Thanks for clarifying it. :slight_smile: