So let's no work on that PHP container
now that we got the nginx container.
The PHP container will be relatively straight forward.
Here, I actually want to use a custom docker file though
because there is no finished image
which has everything I need.
Just to clarify that, if you search for a PHP on docker hub,
you will find an official image
and we are going to use that.
But I actually wanna build a custom image,
building up on that image because I don't just want PHP,
I also want to install some extra extensions
which laravel needs.
So therefore I'll add a new folder
next to the nginx folder, which I'll name dockerfiles.
And in there, I'll add a php.dockerfile.
The name is generally up to you,
but by using this naming pattern,
I ensure that visuals to do code,
the texters as a docker file
and helps me out with some auto-completion.
So in here, I will start with the PHP base image,
which I just showed you.
I'll use that.
And here if you go to tags,
we also have multiple tags to choose from.
I will use the 7.4-fpm-alpine image,
which is a great PHP image,
very slim, and has everything we need here.
Then I will run a command.
And that's the reason why I'm building this custom image.
I'm running a command where I will install
some extra dependencies which we need
and conveniently, in this base image
there is a tool which we can use to install that.
And that's the docker-php-ext-install tool.
Yes, it has a strange name.
Where we can install the pdo,
and pdo_mysql extensions
and these are our PHP extensions, which we need.
Now, we need to ensure that this command
is executed in the right folder.
And therefore we should set a working directory
to /var/www/html.
This folder might look strange,
but it is a pretty standard folder on web servers
to serve your website from.
So we will actually ensure that in all the containers
we're going to build throughout this module,
we always use this as the folder
which should hold our final application.
At the moment, we already saw this folder once,
here in the nginx config,
assuming that it finds the web application files
in that folder, or to be precise in a sub folder of it.
And we'll stick to that folder for all this entire module
because this will be the folder,
which in the end inside of the containers
should hold our laravel PHP application.
So that's why I switched to this folder
as a working directory and why I then install
these extra dependencies there.
Now with that, we're finished with this image
or with this docker file,
and you will know it does one thing.
We don't have a command or an entry point here,
instead we end with the run instruction.
Now up to this point, in the course,
in our docker files,
we always had some command instruction at the end,
here we don't.
If you don't have a command or entry point at the end,
then the command or entry point of the base image
will be used if it has any.
And this base image here, this php base image
will have a default command which is executed
which in the end is a command that invokes
the PHP interpreter.
So this image which we're building here
will then automatically run this default command
of the base image.
And therefore it will be able to deal
with incoming PHP files that should be interpreted
because our base image is invoking this interpreter.
And that's just something I wanted to clarify here
because it is important to be aware of that.
With that, we prepared this docker file.
In the docker compose file we can now reference
this docker file.
So here we can add the build,
set up the build configuration
and now it's not enough to just point
at the docker files folder,
because the file in there is not named just dockerfile.
Instead, we now need the more detailed configuration
which I showed you in the last section.
here, we now specify the context,
which is the folder to find this file in,
in this case, it's dockerfiles.
And then we specify dockerfile
to let composer know about the name of the docker file
that should be used here.
And in this case, that's php.docker file written like this.
And then docker compose will be able to find that file
and built the respective image.
Okay, so now we've got the image set up for this container.
Now, there are two other things we got to do here.
The first very important thing we have to do here
is we have to ensure that this php interpreter
can reach our source code.
Now we have no source code yet,
but we will have some source code,
our php laravel application source code later.
And that source code in the end needs to be available
in this folder instead of the container.
So what we'll need is a bind mount,
because I want to work on that source code
in my project folder, of course.
So I want to Mount my project folder
or some sub folder here into this folder
inside of the container.
Hence I'll start by creating a new folder
on my local host machine in this project folder,
and I will name it SRC for source.
But you can of course also pick a different name here.
And then we can add volumes here to the PHP container
and add one volume.
And that's a point mount pointing at the source folder
on our local machine.
And we'll then mount this to the var/www/html path
inside of the container.
Here we can then actually, by the way,
also improve performance a little bit
by adding delegated after a colon at the end,
we haven't seen that before,
in the end that means that if the containers
should write some data there,
it's not instantly reflected back to the host machine,
instead it is basically processed in batches, you could say,
and therefore performance is a bit better.
It's a optimization, we don't have to do it here,
but we can add it.
And does this a nice place to introduce it.
So adding delegated here improves performance
since this container shouldn't write frequently
to this folder,
or even if it does the things it does right
don't need to be reflected back
to the host machine instantly.
Because it won't write anything which
we need to access instantly on the host machine.
Read only is not an option
because it will write some data to our disc.
The Laravel framework will also generate
some files when it runs,
for example the views which are sent back
as part of responses.
So therefore this is one important thing,
adding this volume which allows us to have a folder
for our source code and which allows us
to work on the source code
and expose it to the PHP interpreter.
The other important thing is the port on which
this PHP interpreter listens for work you could say.
And this port is actually defined here in nginx conf.
Here, I'm sending requests or PHP requests, you could say,
We could say to port 3000.
But first of all here, I have an address.
And that could be an IP address here,
something like this.
But I'm actually utilizing the fact
that all the containers created in one docker compose file
are part of the same network
and can discover each other by name.
So by the names specified here as services,
as long as the code executes inside of the container,
which definitely will be the case here.
So here I'm referring to the PHP container
by using its name.
And hence, if you chose a different name here
for this service, you also need a different name here.
And then I basically want to,
well send my request to handle some PHP file
to port 3000.
And that means that here in docker compose,
I wanna ensure that this port is being used.
Now by looking into the docker file,
of this official PHP image,
which I opened here on GitHub,
we see that this image actually exposes
port 9,000 internally.
So that is what will be exposed by the container.
And again, I'm on the GitHub page of this PHP Docker image,
and then navigate it down into some folders
to view the docker file of the image we're using.
So the container exposes port 9000.
I actually expect port 3000 here,
and they are four here,
we have to map 3000 to 9000.
We have our host machine first
and then we have our container internal port.
However, this is now the tricky part.
Is this really something we need here?
Keep in mind that in the end, it's our nginx server
which wants to talk to this PHP container.
Which is why we're referencing it by name here.
Well, if that's the case,
this port is going straight to the container
and it's not going to be sent from our local host machine.
So this mapping won't do anything here.
Hence, whilst we can map here
in case we want to interact with that PHP container
from our host machine, we actually don't need to do that
just to send a request here.
Instead we should change this and the nginx config
to port 9000.
And I just want to emphasize why we're doing that,
because we have direct container to container communication.
Not through our local host.
So with that changed and yet nginx config,
we are now done and we finished this PHP container.
Let's now move on to the, mysql container.