Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
kubernetes nginx php-fpm pod
# Create a pod containing the PHP-FPM application (my-php-app)
# and nginx, each mounting the `shared-files` volume to their
# respective /var/www/html directories.
kind: Pod
apiVersion: v1
metadata:
name: phpfpm-nginx-example
spec:
volumes:
# Create the shared files volume to be used in both pods
- name: shared-files
emptyDir: {}
# Add the ConfigMap we declared above as a volume for the pod
- name: nginx-config-volume
configMap:
name: nginx-config
containers:
# Our PHP-FPM application
- image: my-php-app:1.0.0
name: app
volumeMounts:
- name: shared-files
mountPath: /var/www/html
# Important! After this container has started, the PHP files
# in our Docker image aren't in the shared volume. We need to
# get them into the shared volume. If we tried to write directly
# to this volume from our Docker image the files wouldn't appear
# in the nginx container.
#
# So, after the container has started, copy the PHP files from this
# container's local filesystem (/app -- added via the Docker image)
# to the shared volume, which is mounted at /var/www/html.
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "cp -r /app/. /var/www/html"]
# Our nginx container, which uses the configuration declared above,
# along with the files shared with the PHP-FPM app.
- image: nginx:1.7.9
name: nginx
volumeMounts:
- name: shared-files
mountPath: /var/www/html
- name: nginx-config-volume
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
@matthewpalmer

This comment has been minimized.

Copy link
Owner Author

@matthewpalmer matthewpalmer commented Jul 21, 2018

From the guide on using Kubernetes/PHP/Nginx

@antonbormotov

This comment has been minimized.

Copy link

@antonbormotov antonbormotov commented Oct 12, 2018

@matthewpalmer shouldn't it sound # Create the shared files volume to be used in both containers, not pods?

@arata-honda

This comment has been minimized.

Copy link

@arata-honda arata-honda commented Jan 24, 2019

@matthewpalmer
Maybe, It should add imagePullPolicy: IfNotPresent under image: my-php-app:1.0.0

@HexalGJ

This comment has been minimized.

Copy link

@HexalGJ HexalGJ commented Jun 25, 2019

Hello,

In fact, if nginx and php containers are in the same pod ( X containers, 1pod ), they share the same FileSystem...
kubectl -n default exec -it phpfpm-nginx-example-XXXXXX-XXXXX -c nginx -- ls /app

You dont need to share a volume !
You dont need to 'postStart'!
ps: an initContainer is better for initData than a postStart.

Best regards

@hetii

This comment has been minimized.

Copy link

@hetii hetii commented Jul 12, 2019

@HexalGJ, IMHO the file systems between them are not shared and by default are isolated, as you may use totally different base images.

To have common shared space you can use emptyDir{} but I have problem with it, because following reason:

  1. emptyDirs start empty, so you need to initialize it.
  2. emptyDirs usualy point to some directory in host side, so you can notice performance issue if your Kubernetes stand on slow virtual machine in cloud provider.
  3. emptyDirs are not shared across replicas pods, so when you scale your deployments to 10 and in start initialize emptyDir by copying your web content it will consume on host side 10x space, so it`s huge waste of resources.

Another option is to have shared hostPath but again it`s not a perfect:

  1. Again you use path that can bind to your vm storage with AKS, so have performance2 issue.
  2. Your hostPath can be shared across replicas instances, but if you plan to have some blue-green deployments then you need to build own mechanism that will store data in different directories to avoid conflicts and finally purge data that belong to old not used deployments.

In theory you can use PVC as a storage for your www data but there is another set of problems:

  1. You can bind them to one namespace, so you can forget to have logical separation of your domains in k8s namespaces.
  2. In theory you can request many PVC, each one per namespace, but smaller PVC usually have less IOPS then big one and you will be charge for each separately(at least in azure).
  3. Problem about blue-green deployment also occur here ;<

I don't know how this looks in different cloud providers, but at lest in azure aks there is no way to have single PVC based on SSD and share it across nodes. You can mount disk based on AzureFile but it's a samba share that use regular spinning disk, so it's slow.

@sinamiandashti

This comment has been minimized.

Copy link

@sinamiandashti sinamiandashti commented Aug 21, 2019

@math

From the guide on using Kubernetes/PHP/Nginx

this solution is not working when you have 1 GB of software ... that cp command is taking long on copying stuf into var/www/html folder

@chatchaisi

This comment has been minimized.

Copy link

@chatchaisi chatchaisi commented Feb 3, 2020

Why mountPath: /var/www/html both image: my-php-app:1.0.0 and image: nginx:1.7.9 ?

@robertodormepoco

This comment has been minimized.

Copy link

@robertodormepoco robertodormepoco commented Mar 3, 2020

Why mountPath: /var/www/html both image: my-php-app:1.0.0 and image: nginx:1.7.9 ?

php-fpm deals with php files, not assets like css/js/images

@mariojacobo

This comment has been minimized.

Copy link

@mariojacobo mariojacobo commented May 15, 2020

for PHP-heavy solutions like Drupal/Magento, this approach won't work. If you have several tens/hundres of thousands of files that you need to copy on every single scaled up POD, it will bring the app down to a crawl. I'm quite surprised that there's no straight-forward solution to sharing a folder from one container to another. for example, let's say I bake the Drupal code into the NGINX image; nginx will serve content from e.g. /usr/share/nginx/html/drupal , but the other container (php-fpm) won't have access to these files, so no dice, app won't run.

Seems we still need to rely on a distributed filesystem like NFS and the like. we need to precreate the volumes, copy over all the code and then deploy the app. This is fine (albeit cloud-based NFS solutions can be slow), however we can't do proper CI/CD for the code upgrades/patches. either we need to create a secondary volume with new codebase, or stop the app, upload the changes and then resume.

We've also looked into postStart actions, but given the number and size of the files, it will take a couple of minutes to finish up. this leads to errors as the entrypoint is executed before the postStart and perhaps half the files have been cloned/copied.

@alekc

This comment has been minimized.

Copy link

@alekc alekc commented Jun 19, 2020

The copy operation should be performed from an init container, in that way pod will not be marked as available until the copy operation is finished.

@JulienBreux

This comment has been minimized.

Copy link

@JulienBreux JulienBreux commented Jun 26, 2020

Example for Laravel v6 / PHP 7.4

# ...
      initContainers:
        - name: shared-code
          image: org/custom-laravel-service:x.y.z
          command: [sh, -c]
          args: ['cp -r /var/www/html/* /data && chown www-data:www-data -R /var/www/html']
          imagePullPolicy: Always
          volumeMounts:
            - mountPath: /data
              name: shared-code
          resources:
            requests:
              cpu: 100m
              memory: 64Mi
            limits:
              cpu: 1000m
              memory: 256Mi
      containers:
        - name: nginx
         image: nginx:1.19-alpine
          volumeMounts:
            - name: shared-code
              mountPath: /var/www/html
              readOnly: true
#...
@mariojacobo

This comment has been minimized.

Copy link

@mariojacobo mariojacobo commented Jun 26, 2020

@JulienBreux - how many files do you have in /var/www/html ? In our custom Drupal code, we are reaching upwards of 50K files, which takes somewhere around 10min to copy. It makes Kubernetes a no go unfortunately.

@carnage

This comment has been minimized.

Copy link

@carnage carnage commented Jul 4, 2020

The easy solution to this is not to copy stuff. Build an nginx container with your static resources in it; use a cloud storage solution to store dynamically uploaded content. see: https://carnage.github.io/2019/10/opencfp-on-gke for a full example

@asimonf

This comment has been minimized.

Copy link

@asimonf asimonf commented Apr 29, 2021

If you have large amounts of files, the simplest solution (although not very dockery) is to put both nginx and php-fpm on the same container and use something like supervisor. People don't like it, but the solution proposed here is a no-go when folders are large. Besides it being wasteful too.

@hiteshacc24

This comment has been minimized.

Copy link

@hiteshacc24 hiteshacc24 commented Aug 13, 2021

For Drupal S3 module is now in Beta mode, and I have tested it out on our lower environments. It works fine. There is no need to copy all the files each time a container is created. Are you running composer install before creating the image or after the pod is created?

@JulienBreux

This comment has been minimized.

Copy link

@JulienBreux JulienBreux commented Sep 3, 2021

@JulienBreux - how many files do you have in /var/www/html ? In our custom Drupal code, we are reaching upwards of 50K files, which takes somewhere around 10min to copy. It makes Kubernetes a no go unfortunately.

One index.php ! Because our statics assets are on another public URL.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment