0

I'm setting up a little web project for studies purpose consisting in two docker containers (a nginx container and a php container).

I've linked my containers and I'm now able to request both static files (.js, .css ...) directly from the nginx container and requests on /index.php through a socket to the php container.

But so far I'm not able to process requests on /.

I'm relying on this example to build my nginx configuration. The code sample and explanation bellow caught my attention :

location / {
    index   index.html index.php;
}

[...]

location ~ \.php$ {
    fastcgi_pass  localhost:9000;
    fastcgi_param SCRIPT_FILENAME
                  $document_root$fastcgi_script_name;
    include       fastcgi_params;
}

[A request “/”] is matched by the prefix location “/” only, therefore, it is handled by this location. Then the index directive tests for the existence of [index.php]. [If it] exists, then the directive does an internal redirect to “/index.php”, and nginx searches the locations again as if the request had been sent by a client.

Since I'm using docker containers the nginx process and php workers work in two different filesystems. So the index.php file is in the php container and not in the nginx. Therefore nginx won't find this file and return a 404 error.

Does that mean that I should -even if it sounds dirty to me- copy the php sources twice, in both containers? Or is there a better way to solve this problem? Would returning a 301 to /index.php be the right way?

vmonteco
  • 10,994
  • 12
  • 43
  • 73

2 Answers2

1

You need to use docker persistent storage, aka volumes.

Move your project files to it, and when container starts you need to map project files to each docker container. (Docker will do it through symlinks)

Then, your nginx container will route to same place where php container use project files and all will work fine.

Details regarding docker persistent storage you can find in this answer: How to deal with persistent storage (e.g. databases) in docker

Also, my advice is to use docker-compose tool. Manage several containers and volumes is extremely easy with it. It's use YAML format config, for example volumes setup will looks like this:

volumes:
# Just specify a path and let the Engine create a volume
- /var/lib/mysql

# Specify an absolute path mapping
- /opt/data:/var/lib/mysql

# Path on the host, relative to the Compose file
- ./cache:/tmp/cache

# User-relative path
- ~/configs:/etc/configs/:ro

# Named volume
- datavolume:/var/lib/mysql

My advice is to generate ready YAML with phpdocker.io, this will help you to understand how to build a good docker ecosystem and move fast.

KorbenDallas
  • 683
  • 7
  • 13
  • Well I guess that must be a way to do it. But still, using these files in the nginx container just to test their existence sounds a bit exaggerated. Thanks for your suggestion. I think I'll make this. – vmonteco Jul 26 '17 at 20:05
  • With volumes, your files would be in one place. Each container will just `see` them through symlink, there will be no exaggerate :) – KorbenDallas Jul 26 '17 at 20:10
  • Volumes are persistent, so what happens when the code needs to be updated? Does this lose the capability to deploy purely by updating the Docker image? – giorgiosironi Feb 05 '18 at 11:19
  • @giorgiosironi, yes. But if you put code into docker image, you will also need to put there Nginx (because it can't see other container files without volumes) and your container can get a huge size (code + more deps like CRON). These are two separate ways, and you need to decide how you will handle it. – KorbenDallas Feb 05 '18 at 11:39
1

nginx is not actually doing anything with that file. It's essentially coming to that file, realising it needs to run through php-fpm, at which point it asks it "hey, fpm, excecute this file at this location and return the output"

Thus, index.php needs to exist at the exact same location for both fpm and nginx, as nginx does check the file exists before getting hold of fpm.

That being said, the contents of index.php don't matter to nginx. When I build containers for a given app, I merely touch /path/to/index.php on the nginx container, and copy the assets nginx does actually serve. You don't need any of your PHP code in there.

On phpdocker.io we mount the whole project at the same location on both nginx and fpm as it's a very simple way to fullfill both requirements (front controller at the same location, and static assets available), but it's not strictly necessary, and indeed you should avoid when actually doing your docker builds as it will fatten up your nginx container for no good reason.

NabLa
  • 98
  • 6
  • This is the first sane answer I see on the topic. Everything based on volumes loses the ability to ship a Docker image as a deployment mechanism, as you have to deploy your source into a persistent volume anyway. – giorgiosironi Feb 05 '18 at 11:22