Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support request: How do you use the FPM version? #284

Open
hkirsman opened this issue Apr 9, 2020 · 33 comments
Open

Support request: How do you use the FPM version? #284

hkirsman opened this issue Apr 9, 2020 · 33 comments
Assignees
Labels

Comments

@hkirsman
Copy link

hkirsman commented Apr 9, 2020

Not sure how it's supposed to work. Could you give some hints?

@ibennetch
Copy link
Member

ibennetch commented Apr 9, 2020

The fpm versions are built against the PHP FPM Docker images. You need to provide a reverse proxy to interface with the phpMyAdmin fpm container. Most often I see people using an nginx container for this.

https://www.linode.com/docs/web-servers/nginx/serve-php-php-fpm-and-nginx/ is one resource that isn't specific to Docker, but gives a good introduction to the concepts. https://stackoverflow.com/questions/29905953/how-to-correctly-link-php-fpm-and-nginx-docker-containers and https://www.pascallandau.com/blog/php-php-fpm-and-nginx-on-docker-in-windows-10/ have some content that is more specific to Docker.

Is there a specific part you're having particular trouble with?

However, if you aren't comfortable setting that up, I really recommend using the Apache image instead which contains everything you need in one image. phpmyadmin/phpmyadmin:latest is the tag I'd recommend.

@ibennetch ibennetch self-assigned this Apr 9, 2020
@lordslair
Copy link

Hello,

I stumbled on this question while trying to achieve this, inside a Kubernetes environment.

The question, docker-style is opened here #253
I read it, tried almost everything, but it's not 100% applicable. Works with pure docker though.

With k8s, the $document_root can't be mounted inside the nginx container, as it is strictly inside phpmyadmin container (the /var/www/html). So nginx fails to serve the static parts.

PHP code is well served by the FPM, no problem with that, I receive a 200 OK
GET /index.php HTTP/1.1" 200 3600
But every other resources end up with a 404 as they are not served by the FPM (not his job), nor by nginx (it doesn't have them locally).

Is there somewhere in the documentation a relevant best practice ?
I can't be the only one trying to achieve this:
Using the fpm build inside a Kubernetes environment, behind a nginx

Thanks,

@ibennetch
Copy link
Member

@lordslair this is a good question. To be honest, I have never tried to run the phpMyAdmin container from a k8s environment, so I don't have an immediate answer for you.

@lordslair
Copy link

Thank you for the answer!

For now I'll probably use the "traditional" Apache version then.
Just pulled it, and it works flawlessly with nginx using a proxy_pass

If you ever have other feedbacks or try a deploy on k8s, I'll be gladly interested by a follow-up
Thanks again,

@ibennetch
Copy link
Member

ibennetch commented Apr 21, 2020 via email

@rpasing
Copy link

rpasing commented Apr 24, 2020

Hey, this was possible before and stopped working after #285

The way I did it before: Just define /var/www/html as external volume, and mount that volume also in the nginx container.

This of course now is not working anymore, as the /var/www/html directory is filled with the files inside of the container, and hence when mounting it from outside, we are overriding the directory from inside the container, and then the directory is empty.

I currently don't see another solution than to write a custom entrypoint script and therein copy the contents from /var/www/html directory to a custom directory (e.g. /opt/phpmyadmin), and mount to use that custom directory as a shared volume mount for the nginx container too.

Other suggestions are very welcome. It's a bit sad to see that #285 is breaking existing setups :(

@williamdes
Copy link
Member

@rpasing I have an idea, what about having an ENV flag to create symlink to a specific folder at start time ?

@ibennetch
Copy link
Member

Sorry I'm not quite getting what's wrong here @rpasing. What is it you're trying to do here that isn't working? The Kubernetes environment or anything with fpm?

@ibennetch
Copy link
Member

If we have a good reason to revert #285, we certainly can do that because the only reason we do it is from the suggestion at docker-library/official-images#7288. It seems to be an improvement, but if I missed some cases like these that it breaks then we can find a better solution.

@rpasing
Copy link

rpasing commented Apr 24, 2020

hm?

Previously I had something like this in my docker-compose.yml under a container using the phpmyadmin/phpmyadmin:fpm-alpine image:

volumes:
  - /var/www/phpmyadmin/:/var/www/html/

Before #285 that would result in the PMA files being available on the host in the directory /var/www/phpmyadmin, because the entrypoint-script of the PMA container copied the files into the /var/www/html container after the container started, so after the directory has been mounted.

And then I could have in my nginx docker-compose something like:

volumes:
  - /var/www/phpmyadmin/:/var/www/phpmyadmin/:ro

And in the nginx server definitions I could hence reach the static files of PMA from inside the nginx container.

Now, with the changes from #285, the files inside the PMA container in directory /var/www/html are being placed there at container-buildtime (and not after container-startup), so when I mount a directory there after the container started, it will be empty (because the host-directory is empty, and it is beign mounted inside of the container).

Is it clearer now?

@ibennetch
Copy link
Member

Ah, yes, thank you. That does make sense now. Sorry it's just my inexperience with docker-compose that makes more difficult some things that should be obvious :-) I appreciate your explanation.

Seems to me like you have a great reason for us to revert #285. I can't think of any other workaround that would be suitable.

@rpasing
Copy link

rpasing commented Apr 24, 2020

Actually, I think we should think about a better solution than to just revert #285. I think so because also with the previous approach there were some problems.

For example were PMA-updates not easily doable, because the host always held a non-empty version of the PMA files, and the entrypoint-script then never actually replaced the files with a newer version. My workaround for that was to clear that directory before each container-startup, so that the directory is empty then and the entrypoint-script placed the new files there...

@rpasing
Copy link

rpasing commented Apr 24, 2020

As far as I know other PHP-projects just do the extraction of the soure-files in the entrypoint-script, and not in the Dockerfile. So instead of downloading to /usr/src/phpmyadmin in the Dockerfile and copying to /var/www/html in the entrypoint, what about downloading+extracting to /var/www/html in the entrypoint, and don't do it in the Dockerfile?

@ibennetch
Copy link
Member

Hm, that's an interesting case I hadn't considered. I'll have to look further at some of the options here. I appreciate your suggestions.

@ibennetch
Copy link
Member

As far as I can think through, there would never be a scenario where config.inc.php is placed in /var/www/html/ — it always belongs in /etc/phpmyadmin or as environment variables passed to Docker. Does anyone disagree?

@williamdes
Copy link
Member

As far as I can think through, there would never be a scenario where config.inc.php is placed in /var/www/html/ — it always belongs in /etc/phpmyadmin or as environment variables passed to Docker. Does anyone disagree?

Hmm, I think you are pointing out the case where the config would not be written in he root that the user choose to be right

@ibennetch
Copy link
Member

Sorry, I think my question just came from nowhere and I should have explained better.

I'm working through the logic of resolving this, and want to correctly handle any situations with the mounted volume. I think that if there's a new phpMyAdmin version, we should just overwrite what's in /var/www/html/, but had a nagging concern that there could be a scenario where a user puts their config.inc.php there. But I think that's not possible.

@williamdes
Copy link
Member

Sorry, I think my question just came from nowhere and I should have explained better.

I'm working through the logic of resolving this, and want to correctly handle any situations with the mounted volume. I think that if there's a new phpMyAdmin version, we should just overwrite what's in /var/www/html/, but had a nagging concern that there could be a scenario where a user puts their config.inc.php there. But I think that's not possible.

My idea is:

  • use default folder
  • add an env variable to change the root location
  • add an env variable to fill the root directory with our stored data
  • use the same or add one more to manage the configurations filling process ?

@J0WI
Copy link
Contributor

J0WI commented May 6, 2020

If you revert #285 you may also want to revert parts of https://github.com/phpmyadmin/docker/pull/286/files#diff-80edf79b0f382a3c6e871ac209ffd6ab to restore the custom user feature. Currently www-data is hardcoded.

@ibennetch
Copy link
Member

If you revert #285 you may also want to revert parts of https://github.com/phpmyadmin/docker/pull/286/files#diff-80edf79b0f382a3c6e871ac209ffd6ab to restore the custom user feature. Currently www-data is hardcoded.

Yes, thanks, that's a good suggestion.

@ibennetch
Copy link
Member

  • use default folder
  • add an env variable to change the root location
  • add an env variable to fill the root directory with our stored data
  • use the same or add one more to manage the configurations filling process ?

This feels quite complex to me, is such a system worthwhile?

@williamdes
Copy link
Member

  • use default folder
  • add an env variable to change the root location
  • add an env variable to fill the root directory with our stored data
  • use the same or add one more to manage the configurations filling process ?

This feels quite complex to me, is such a system worthwhile?

Maybe reverting the diff would be easier.
Anyway it did not cause us trouble as far as I know

@tianon
Copy link
Contributor

tianon commented May 7, 2020

The problem with the shared volume is that it's essentially a deployment crutch, and it's inherently fragile.

What I'd suggest instead of a shared volume (which is going to ultimately limit scalability) is a short Dockerfile copying the relevant static files from the phpmyadmin image into a new nginx-based image, which can then be scaled separately within the cluster without having a corresponding phpmyadmin container running on every host; something like:

FROM nginx:1.17
COPY --from=phpmyadmin/phpmyadmin:5.0 /var/lib/www /usr/share/nginx/html

You could even go further by pre-baking the NGINX configuration into this image (thus making deployment even simpler).

If you don't need the scalability/performance of NGINX + FPM, that's the use case of the Apache-based default image (which should also work fine behind NGINX, if multiple applications need to run behind the same external port).

@J0WI
Copy link
Contributor

J0WI commented May 7, 2020

@tianon thanks for sharing your thoughts!

We actually have the same discussion in nextcloud/docker#968. I have some concerns with this variant that the two images may get out of sync.

Would you accept this nginx stub image in the library or how can we distribute it?

Another use case for NGINX + FPM is if you use a shared webserver/proxy and multiple FPM applications. But then prebuild nginx stubs are pretty useless.

@tianon
Copy link
Contributor

tianon commented May 7, 2020

I think if you've got multiple FPM applications, the easiest way is to leverage Docker's "copy up" functionality (https://docs.docker.com/engine/reference/commandline/service_create/#options-for-named-volumes, default enabled for -v but default disabled for --mount) and --volumes-from on your NGINX instance (which also then creates the appropriate "dependency" relationship), but I think that's significantly more complex to accomplish on something like Kubernetes, and is still very fragile.

The reality here is that FPM is difficult to deploy and use in Docker (it wasn't really designed for Docker, after all -- they expect to run on the same host as whatever consumes their FastCGI socket, which is reasonable from the perspective of when it was written). Adding another variant that pre-bakes the NGINX configuration is a band-aid to this problem, although it's a slightly less fragile one (IMO) than sharing volumes with container image source code in them? Given the number of users we've seen over the years complaining about how to use the Wordpress FPM variants, I imagine you'll probably see a lot of users who used the NGINX variant and are wondering why it doesn't "seem to work" (because it won't execute any PHP scripts by itself).

I guess I'm really coming back to whether there's something wrong with just using Apache and letting one container be your "source of truth" for the phpMyAdmin application? 😄

(Maybe NGINX could be convinced to make a new official image variant for NGINX Unit? 😄)

@rpasing
Copy link

rpasing commented May 9, 2020

Sorry, I didn't really follow this discussion here anymore. What are the results of your thoughts?

What I read so far ("just use the apache-based phpmyadmin image") is not really satisfying: Of course I can proxy that apache httpd through my "external webserver" (which in this case is nginx), but why should I let a full-blown instance of Apache be running just to serve some small static files, which could get served from the nginx directly if it had access to the files? That sounds very unefficient.

A stupid workaround for me for the time being would to create a "stub container" based on Alpine which just copies the files from the phpmyadmin image (like shown above, but now based on Alpine and not nginx) and write an entrypoint script which copies the copied files into a shared volume mount and exits directly afterwards. As I said, stupid workaround.

From my point of view the phpmyadmin php-fpm image should be able to handle a volume mount as storage for its sourcefiles. And that's my problem, it currently doesn't. All "solutions" to this are just workarounds till now.

@hbielenia
Copy link

I found this discussion while looking for information on using fpm images, since instructions from here no longer work. Just wanted to state it clearly because it may not be evident from this thread: as far as I can tell, the change made in #285 makes fpm images completely unusable. Those images require a separate web server to handle static files and without shared directory, paths can't be handled correctly. The change you've made means they're no longer able to work with external server, and of course those images don't provide one on their own (since that's the entire point of having them).

For the time being, people can just resort to use "main" (Apache-based) image, but in my opinion reverting #285 should take priority, as it turned out to be a very breaking change. Discussing better solution can take place afterwards.

@pzystorm
Copy link

pzystorm commented Sep 1, 2020

Ah, yes, please revert it.
I've just hit exact this problem and commented it already here:
#253 (comment)

Apache is no alternative. For the time being I would say I dont use this screwed up phpmyadmin fpm docker image and use my own nginx/fpm docker image and install phpmyadmin from source by my own.

@qeepcologne
Copy link

i came to the same conclusion when i tried to use it with haproxy (#327), fpm is not usable.

@huancz
Copy link

huancz commented Apr 11, 2022

I stumbled here after painful experience of trying to make alpine version work. I was just trying to have "quick" solution for one of our contractor's request to have access to phpmyadmin on already dockerized wordpress installation. The discussion here steered in a direction that I can't really follow, but I think this post fits at least OP question.

My problem was mainly that my background is c#/dotnet + usual linux devops, last I touched php was some 15 or 20 years ago. I had no idea what fpm is and how it differs from normal php hosted via apache module, in my head I just assumed it's some nickname for phpmyadmin version itself, like those ubuntu release names. Certainly nothing to worry about. I was just trained from previous experience with docker that alpine version is that one to get, unless I have special needs, and fpm was the only alpine version available, so... why not?

Docker hub description doesn't hint at any pitfalls either - just use the image and it will listen on guest port 80, easy. Only the usual caveats of alpine distribution - different libc etc - something image builder should worry about, not user of that image. Even error messages I get from links or curl on host are very similar, unless I pay close attention ("connection timed out" vs. "connection reset by peer". Which is what pointed me at the right direction when I finally did notice it).

tl;dr:
Few words on dockerhub that mention current state of alpine-fpm and that it cannot serve http traffic directly without external fastcgi proxy would have been very helpful.

@Eagle3386
Copy link

Docker hub description doesn't hint at any pitfalls either - just use the image and it will listen on guest port 80, easy. Only the usual caveats of alpine distribution - different libc etc - something image builder should worry about, not user of that image. Even error messages I get from links or curl on host are very similar, unless I pay close attention ("connection timed out" vs. "connection reset by peer". Which is what pointed me at the right direction when I finally did notice it).

Thanks so much for this hint - Firefox only showed the 502 Bad Gateway error that my Synology NAS threw at me, the logs where pretty much empty & only using Curl revealed the real error (Connection reset by peer).

tl;dr: Few words on dockerhub that mention current state of alpine-fpm and that it cannot serve http traffic directly without external fastcgi proxy would have been very helpful.

Can you (or @ibennetch or maybe @williamdes) explain to me what needs to be changed in order to get this working on a Synology NAS using Docker & its built-in reverse proxy (Nginx)?
Because Synology's own PMA is stuck with 4.x versions & I'd therefore really like to get PMA working (preferably as fpm-alpine flavor)?

@PittyXu
Copy link

PittyXu commented Jan 5, 2024

My solution is overwrite the docker-entrypoint.sh .

docker-compose.yml:

nginx:
  image: nginx:alpine
  container_name: nginx
  ports:
    - "80:80"
  volumes:
    - ./conf:/etc/nginx/conf.d
    - ./html:/usr/share/nginx/html
php:
  image: phpmyadmin:fpm-alpine
  container_name: php
  entrypoint:
    - /var/www/docker-entrypoint.sh
  command: php-fpm
  volumes:
    - ./docker-entrypoint.sh:/var/www/docker-entrypoint.sh
    - ./html:/scripts
    - ./html/phpmyadmin:/var/www/phpmyadmin

/etc/nginx/conf.d/default.conf:

server {
    listen  80;
    root /usr/share/nginx/html;

    location / {
        try_files $uri /index.php$is_args$args;
    }

    location ~ ^/.+\.php(/|$) {
        fastcgi_pass php:9000;
        include fastcgi_params;
        fastcgi_index  index.php;
        fastcgi_split_path_info ^((?U).+\.php)(/?.+)$;
        fastcgi_param   SCRIPT_FILENAME   /scripts$fastcgi_script_name;
        fastcgi_param   PATH_INFO         $fastcgi_path_info;
        fastcgi_param   PATH_TRANSLATED   /scripts$fastcgi_path_info;
    }
}

./docker-entrypoint.sh

#!/bin/bash

CONTAINER_ALREADY_STARTED="CONTAINER_ALREADY_STARTED_PLACEHOLDER"
if [ ! -e ../$CONTAINER_ALREADY_STARTED ]; then
    touch ../$CONTAINER_ALREADY_STARTED
    echo "-- First container startup --"
    /bin/cp -rfT /var/www/html/. /var/www/phpmyadmin/
else
    echo "-- Not first container startup --"
fi

/docker-entrypoint.sh "$@"

@armada45-pixel
Copy link

My solution.

docker
├── docker-compose.yml
├── nginx
│   ├── log
│   │   └── host.access.log
│   ├── config
│   └── nginx.conf
│
└── phpmyadmin
    ├── config.user.inc-v2.php
    └── theme
        ├── blueberry
        ├── boodark
        └── darkwolf

nginx.conf

worker_processes 1;

events {
   worker_connections 1024;
}


http {
   include mime.types;
   default_type application/octet-stream;

   log_format main '$remote_addr - $remote_user [$time_local] \t'
   '"$request_method" - "$request_uri" - "$server_protocol" \t'
   '$status $body_bytes_sent "$http_referer" \t'
   '"$http_user_agent" "$http_x_forwarded_for" \t'
   # '$request_time \t'
   ' req_body:"$request_body" \t'
   '$upstream_response_time ms';
   # 'resp_body:"$resp_body"';

   access_log /var/log/nginx/host.access.log main; # store access log on host

   sendfile on;
   tcp_nopush on;
   tcp_nodelay on;

   types_hash_max_size 2048;
   #keepalive_timeout  0;
   keepalive_timeout 65;

   client_max_body_size 50M;

   gzip on;

   server {
       server_name localhost;
       add_header X-Frame-Options "DENY";
       listen 80;
       listen [::]:80;

       root /var/www/html;  # path where phpmyadmin place
       index index.php;

       location ~ \.php$ {
           try_files $fastcgi_script_name =404;

           fastcgi_pass cs_phpmyadmin_FPM:9000;  # cs_phpmyadmin_FPM is name of container / Easier then using ip / or you can use ip instead of name like 172.0.16.1
           fastcgi_index index.php;
           fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
           include fastcgi_params;
       }

       ## Images and static content is treated different
       location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico|xml)$ {
           access_log off;
           expires 30d;
       }

       location ~ /\.ht {
           deny all;
       }

       location ~ /(libraries|setup/frames|setup/libs) {
           deny all;
           return 404;
       }
   }
}

docker-compose.yml

version: "3.8"

services:
 cs_phpmyadmin_FPM:
   image: phpmyadmin:fpm-alpine
   ports:
     - "9000:9000/tcp" # or "9123:9000/tcp" and Don't forget to change in nginx.conf "fastcgi_pass"
   volumes:
     - "./phpmyadmin/theme/blueberry:/var/www/html/themes/blueberry"
     - "./phpmyadmin/theme/boodark:/var/www/html/themes/boodark"
     - "./phpmyadmin/theme/darkwolf:/var/www/html/themes/darkwolf"
     - "./phpmyadmin/config.user.inc-v2.php:/etc/phpmyadmin/config.user.inc.php"
     - phpmyadmin-file:/var/www
   secrets:
     - phpmyadmin-config

 cs_nginx:
   image: nginx:alpine
   ports:
     - "8090:80/tcp" # nginx expose port 80 for development i change to 8090
   volumes:
     - "./nginx/config/nginx.conf:/etc/nginx/nginx.conf"
     - "./phpmyadmin/theme/blueberry:/var/www/html/themes/blueberry" # for some resaon need to volume theme again
     - "./phpmyadmin/theme/boodark:/var/www/html/themes/boodark"
     - "./phpmyadmin/theme/darkwolf:/var/www/html/themes/darkwolf"
     - phpmyadmin-file:/var/www
     
secrets:
 phpmyadmin-config:
   file: ./phpmyadmin/config.user.inc-v2.php

volumes:
 phpmyadmin-file: # use top-level volumes for link file content from phpmyadmin to nginx

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests