I'm studying Docker, and most of the resources I've watched and followed copies the source code twice. One to the containerized php
image and containerized nginx
image.
services:
php:
...
volumes:
# This line copies the source code to the php container's ./:/var/www
- ./:/var/www
nginx:
...
volumes:
# This line ALSO copies the source code to the nginx container's ./:/var/www
- ./:/var/www
Since nginx
and php
are running on separate containers each with a different underlying linux distro, how and why does this work?
I understand a containerized database service communicating with the php
app because that happens via the docker network through the specified port
, but how does that concept work with nginx
and php
? And why do we copy the same file to the same location in different containers twice?
Traditionally, on a dedicated server you install nginx
AND php
so that the web server can run .php
files. But how does that work with Docker?
CodePudding user response:
PHP has a somewhat unusual setup, compared to more modern Web stacks. A typical setup has a PHP-FPM interpreter that executes PHP scripts in response to requests; but, this doesn't speak HTTP but rather a separate protocol (FastCGI), and it can't serve static assets.
This leads to a setup where you in fact need two containers. In the example you show, the php
container most likely speaks the FastCGI protocol and executes PNP scripts. The nginx
container serves HTTP, so you can connect an actual browser to it, and it both directly serves static assets and also forwards requests that should execute PHP scripts on to the other container.
This two-container setup is somewhat specific to PHP, though not totally. Almost every other Web framework directly serves HTTP and also can serve its own static assets. So, for example, a Python Flask or Django setup wouldn't necessarily need a separate Nginx reverse proxy. A Go or Java application often would build the static assets into the application itself (the built Go binary or a Java .jar
file) and they might not even specifically be mentioned in a Dockerfile. You could still want a reverse proxy if you have multiple back-ends or if you're serving your front-end code from a dedicated container, but you wouldn't necessarily need to inject code into that proxy.
The volumes:
syntax you show is a bind mount. A standard Docker setup builds an application into a reusable image. This setup doesn't do that; instead, it requires the application source code to be present on the host, and then causes it to appear in both containers. The mechanics of the mount are such that the files are never "copied" at all (on native Linux). Nothing stops the same directory from being mounted into multiple containers, and if your static assets and PHP code are intermingled in the same directories this could be a convenient way to serve both.
Since this setup does depend on the code existing on the host, the actual deployment mechanics are very similar to a non-Docker deployment. In both cases you need to install the application code on the target system, and also some software that's able to execute it. The only real difference here is that you're installing Docker instead of a PHP interpreter and an Nginx proxy.