Docker PHP application start - php

I'm trying to run a ready PHP app (a copy of existing site - just want to run it locally) in Docker.
I tried some from that: https://semaphoreci.com/community/tutorials/dockerizing-a-php-application but no luck. One friend told me that I should also have a server for that which confused me a bit. I know PHP have self-hosting capabilities (not recommended for production tho, but I need it just for testing purposes).
I also tried docker run -it --rm --name my-running-script -p 8080:8080 -v /Users/jans/Developer/sfolder:/usr/src/myapp -w /usr/src/myapp php:5.6 bash and run it from bash with php index.php (and yes - I used ls earlier to see if there are any files in there and they are), but nothing happens and localhost:8080 is not available.
I'm also trying to use https://hub.docker.com/r/1and1internet/ubuntu-16-nginx-php-phpmyadmin-mysql-5/ but this is really complicated to me and can't do anything at all with it.
Anyone with experience how to run PHP app will be more than welcome.

Related

Php script won't run on docker localhost

I am very new to Docker so please forgive any technical wording mistakes I make regarding this.
I am trying to get a very basic "Hello World!" php script to run through a localhost docker container. I am trying to run this script to test out this image that contains php and oracle: https://hub.docker.com/r/silencesys/php-oci8
I pulled it using this command: docker pull silencesys/php-oci8
Then I tried to run it with numerous commands, some of them giving me this:
[16-Jun-2022 17:57:12] NOTICE: fpm is running, pid 1
[16-Jun-2022 17:57:12] NOTICE: ready to handle connections
And then some of them give a random string of letters and numbers. I don't know what it refers to but I know that it means that it is running the container. When I open the container's terminal and run 'ls' I can see my index.php file. I can even run 'cat index.php' and see that it contains the proper code in there to run "Hello World!" I will even include the code in here as a sanity check:
<?php
echo "Hello World!";
?>
But everytime that I open up the localhost in my browser, I get this:
This page isn’t working right now
localhost didn’t send any data.
ERR_EMPTY_RESPONSE
I have tried so many variations of this base docker run command that I found here:
docker run -d -p 80:80 --rm --name temp-container -v "$PWD":/var/www/html silencesys/php-oci8
Any help is greatly appreciated!
The docker image you are referring to does contain PHP, but it does not contain a web server.
Servers that serve web pages using PHP consist of a webserver software, that accepts HTTP-requests and communicates to PHP running in the background if needed. It can be thought of an intermediary between the Browser and PHP, and if it is missing the browser cannot access your PHP script.
I haven't found an image that could help you right away, however I stumbled upon this, and it tells that for your usecase you should go for a PHP image that has Apache included (i.e. the name will contain apache in the tag).
The way I solved this was by using this image in conjunction with the image I was using in the Question. Here is a step by step guide of what I did:
Create folder in home/[username] directory
docker pull soivangoi/nginx-php-adminer-oci8
docker pull silencesys/php-oci8
docker run -dit -p 8080:80 soivangoi/nginx-php-adminer-oci8 -v "$PWD":/var/www/ silencesys/php-oci8
4.1. If that doesn't work try this "docker run -d -it -p 8080:80 -v "$PWD":/var/www/ silencesys/php-oci8"
docker run -it -p 8080:80 --rm --name test-container -v "$PWD":/var/www/ soivangoi/nginx-php-adminer-oci8
Bash into the container. Either by command line or by clicking the terminal button on the container.
cd to where your php code is stored.
Run it!
Just make sure that whatever network you are on has access to the oracle database or else it will not let you run your code still.

ORA-28547 with php-fpm in docker container

I got a working php-fpm docker container acting as the php backend to a nginx frontend. What I mean by working, is that it renders phpinfo output in the browser as expected.
My php-fpm container was produced by php-fpm-7.4 prod of the devilbox docker repo. It has OCI8 enable.
The issue: I keep getting ORA-28547 when trying oci_connect
What I have done:
1--add /usr/lib/oracle/client64/lib to a file inside ld.so.conf.d and run ldconfig -v
2--restart docker container.
3-- Now phpinfo shows ORACLE_HOME=/usr/lib/oracle/client64/lib
4--Add tnsnames.ora to /usr/lib/oracle/client6/lib/network/admin (there is a README.md file inside that folder that even tells you to do that)
5--Restart docker container again.
6-oci_connect still fails with the same error.
What I am missing?
Thank you very much for any pointers, I think I have browsed to the end of the internet and back without finding a solution yet.
----SOLUTION: reinstall instantclient, relink libraries (ldconfig) to use new instantclient libraries. Create modified dockerfile to do it when container is created.
I modified the Dockerfile file of the php-fpm to add new instant client files and not the one that were provided by the original file. I was not able to make it work with them. I have tried a few times rebuilding the image (docker-compose up --build) and this is the file that does the trick:
FROM devilbox/php-fpm:7.4-work
#instantclient.conf content: /opt/instantclient
RUN echo "/opt/instantclient" >/etc/ld.so.conf.d/instantclient.conf
WORKDIR /opt
RUN wget https://download.oracle.com/otn_software/linux/instantclient/19800/instantclient-sdk-linux.x64-19.8.0.0.0dbru.zip
RUN wget https://download.oracle.com/otn_software/linux/instantclient/19800/instantclient-sqlplus-linux.x64-19.8.0.0.0dbru.zip
RUN wget https://download.oracle.com/otn_software/linux/instantclient/19800/instantclient-basic-linux.x64-19.8.0.0.0dbru.zip
RUN unzip instantclient-sdk-linux.x64-19.8.0.0.0dbru.zip
RUN unzip instantclient-sqlplus-linux.x64-19.8.0.0.0dbru.zip
RUN unzip instantclient-basic-linux.x64-19.8.0.0.0dbru.zip
RUN mv instantclient_19_8 instantclient
ADD tnsnames.ora /opt/instantclient/network/admin
RUN ldconfig -v
CMD ["php-fpm"]
expose 9000
# Insert following to .bash_profile or .profile of the User starting the php-fpm
export ORACLE_HOME=/usr/lib/oracle/client64
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME/lib
export PATH=$PATH:$ORACLE_HOME/bin
export TNS_ADMIN=$ORACLE_HOME/network/admin
# Test to Ping Remote Db to be connected by PHP
tnsping <tns-name of remote DB - i.e. db12c.world>
# restart here the php Engine
Can you please check
https://github.com/caffeinalab/php-fpm-oci8/blob/master/Dockerfile
which seems to create a p-fpm-oci8 docker image
the "wget" for
wget -qO- https://raw.githubusercontent.com/caffeinalab/php-fpm-oci8/master/oracle/instantclient-basic-linux.x64-12.2.0.1.0.zip | bsdtar -xvf- -C /usr/local &&
wget -qO- https://raw.githubusercontent.com/caffeinalab/php-fpm-oci8/master/oracle/instantclient-sdk-linux.x64-12.2.0.1.0.zip | bsdtar -xvf- -C /usr/local &&
wget -qO- https://raw.githubusercontent.com/caffeinalab/php-fpm-oci8/master/oracle/instantclient-sqlplus-linux.x64-12.2.0.1.0.zip | bsdtar -xvf- -C /usr/local && \
can be dropped when you place downloaded instant client files into local host dir
/usr/local
and extract them - resulting in
/usr/local/instantcient_12_2
or 18, 19c equivalents
the 4 "ln" commands have to be adjusted to reflect the local host instantclient dir
the tnsnames.ora for instantclient is available from host by VOLUME command
-------------FINAL SOLUTION------------(it was not network related, I had done a couple of changes to the files, and also tried a different database, all at the same time, so it made me think that it was the different database what fixed the issue)
After many trial and errors, I came up with a Dockerfile that creates the correct configuration of files and connects without any issues to the database:
--Dockerfile: (to build php-fpm 7.4 using devilbox image)
Final solution:
I modified the Dockerfile file of the php-fpm to add new instant client files and not the one that were provided by the original file. I was not able to make it work with them. I have tried a few times rebuilding the image (docker-compose up --build) and this is the file that does the trick:
FROM devilbox/php-fpm:7.4-work
ADD instantclient.conf /etc/ld.so.conf.d/
WORKDIR /opt
RUN wget https://download.oracle.com/otn_software/linux/instantclient/19800/instantclient-sdk-linux.x64-19.8.0.0.0dbru.zip
RUN wget https://download.oracle.com/otn_software/linux/instantclient/19800/instantclient-sqlplus-linux.x64-19.8.0.0.0dbru.zip
RUN wget https://download.oracle.com/otn_software/linux/instantclient/19800/instantclient-basic-linux.x64-19.8.0.0.0dbru.zip
RUN unzip instantclient-sdk-linux.x64-19.8.0.0.0dbru.zip
RUN unzip instantclient-sqlplus-linux.x64-19.8.0.0.0dbru.zip
RUN unzip instantclient-basic-linux.x64-19.8.0.0.0dbru.zip
RUN mv instantclient_19_8 instantclient
ADD tnsnames.ora /opt/instantclient/network/admin
RUN ldconfig -v
CMD ["php-fpm"]
expose 9000
That's why I have suggested to use tnsping - unfortunaly it is not included in any of the instant client files which is a pity - so you have to pick it up from regular client with matching OS, bitsize and Oracle release. As workaround you could place SQL*Plus package files into container and try to connect with a foo user like
sqlplus foo/foo#\<ip>:\<port>/\<dbname>
which should generate an error - if
user/password not matching - ORA-1017 i.e. DB & listener running
listener running - ORA-1034 i.e. DB down
listener down (no return, or TNS-Errors)
I got it!. It was a firewall issue. I launched a tcpdump capture
session and there was nothing wrong with php-fpm, oci8 and
instantclient libraries. The traffic was initiated but there was no
response from the database. I made it work against a different
database where this box has no firewall issues.
I now will try rebuilding the docker image so I can see what I have to
manually add if any.
That was incorrect (the firewall as the origin of the problem). Rebuilding the docker file showed me where I had it wrong. See original question for solution.

Website hosted in docker container is not updating live

I am developping a website which I want to host inside a php-apache docker container.
I use the following command to run the container:
docker run -dit --restart unless-stopped --name my_www -p 8080:80 -v /path/to/repo:/var/www/html/ php:7.4-apache
Since I bind the repository containing the code as a volume to the container, I expect the website to "update live" when I change the code locally. I had this right behaviour last time I tried but I am now unable to get it back.
When I check the website locally at 127.0.0.1 everything is ok and changes are taken into account normaly, but they do not propagate into the docker container...
For some reason, the files in the docker are stuck to an old version of the code, an old "stat" of the repository...
Any ideas how I can manage to fix this and preview changes live ?
Credits to #Don't Panic for helping to debug.
The browser was caching everything so I couldn't see changes live.
The solution was to enable the "expires" apache module inside the docker container:
$ docker exec -it <container_id> bash
root#<container_id>:# a2enmod expires
root#<container_id>:# exit
$ docker restart my_www
Et voilà :)

Docker + PHP - ERROR: Couldn't connect to Docker daemon?

I'm following this guide to set up a PHP development environment with Docker.
I have created a folder on my desktop docker-php and added a docker-compose.yml file into it, with this content:
nginx:
image: nginx:latest
ports:
- 80:80
On my terminal:
$ cd /home/my-username/Desktop/docker-php/
$ docker-compose up -d
I get this error:
ERROR: Couldn't connect to Docker daemon at
http+docker://localunixsocket - is it running?
If it's at a non-standard location, specify the URL with the
DOCKER_HOST environment variable.
I'm on Xubuntu 16.04.
Or perhaps I should put the folder in the specific location that is required by Docker? If so, which is it?
The most common reason for this error is that you ran 'docker-compose up' without sudo. As long as there is docker installed and is up and running, you are likely missing sudo in the docker command.
You could use native Docker
One option is to abandon docker-machine and use a native Docker setup on your system. Since you are on Linux (Xubuntu), this is an option for you. docker-machine is most often used by people who can't run Docker natively (Mac or Windows), and use it to install a Docker-capable VM and some local commands on their OS to talk to it.
You can find install docs for Docker on Linux here.
However, you already have docker-machine installed, so this may be the most disruptive option for you.
Your docker-machine may not be running
The error you are getting is saying the Docker client cannot talk to the server. One potential reason for this is that your docker-machine VM isn't running. You should verify it is running, and if not, start it.
To get a list of your docker-machines (may be one or more):
docker-machine ls
You will probably have one machine named default, but you may have more, depending on how you did your setup.
You can get the current status with:
docker-machine status <machine-name>
And you can use stop, start, restart to manage the docker-machine.
(More in the Docker Machine CLI reference.)
You need the proper environment set
docker-machine relies on environment variables to work properly. Because you may have multiple docker-machine setups, you have to tell the client which one to use.
To set the environment, you can get it from the docker-machine command.
docker-machine env <machine-name>
And you can automatically inject it into the environment (this may be a useful thing to put into your shell startup file).
eval "$(docker-machine env <machine-name>)"
You should end up with env vars similar to these:
DOCKER_HOST=tcp://192.168.99.101:2376
DOCKER_CERT_PATH=/Users/nathanleclaire/.docker/machines/.client
DOCKER_TLS_VERIFY=1
DOCKER_MACHINE_NAME=dev
Keep in mind you should use the eval form here, not just run the env command and paste the output into your shell setup; it may change on a docker-machine restart, etc, so you can't rely on an old setup to still work later.
If your docker-machine is running, and these env vars are set, your docker and docker-compose commands should work.
Solution:
sudo usermod -a -G docker USERNAME

Recommend way to Artisan on Docker

I am yet to find an elegant and efficient way to run Laravel Artisan commands in my Docker based local dev environment.
Could anybody suggest the recommended or "proper" way to do things like migrations?
Or, has anybody found a neat way of doing this? Ideally with examples or suggestions.
Things that I've considered:
A new container (sharing the same volume and db link) with ssh, just for running commands (seems nasty).
Hacks in supervisor that could then end up running on live (not ideal).
Editing db configs, or trying to hack in a "host" environment, so that at least things like migrate can be run from the host.
Creating web front ends to run things (really nasty).
Trying to build a "signal" for it things.
I'm still getting my head around Docker and it's new-container-for-everything approach.
I suppose I want to balance cool-dev-ops stuff with why-do-I-need-another-fake-server-just-get-it-working-already.
I'd love to commit to it for my dev workflow, but it seems to become awkward to use under certain circumstances, like this one...
Any suggestions and ideas are welcome. Thanks all.
Docker 1.3 bring new command exec
So now you can "enter" running container like
docker exec -it my-container-name /bin/bash
After that you can run any command you want
php artisan --version
The best practice regarding Docker is to run each process inside it's own container. Therefore, the ideal way to run artisan commands is to have an image for creating containers specifically for this purpose.
I've created an image which can be pulled from the Docker Hub dylanlindgren/docker-laravel-artisan and it works really well. It's on GitHub as well if you want to take a look at the Dockerfile behind it.
I've also just written a blog post describing the way that all these seperate containers fit together.
There are a couple of possibilities...
Mounting a host directory in your container as the folder in which your Laravel app lives. That way you can just run php artisan migrate or composer update from the host. You might have problems with deployment, though, since you would have to replicate that part of your environment on the server.
adding an SSH server to your container (which is not recommended; here's a good discussion of that).
build and use nsenter, a tool for "entering" a running container and getting shell access. Note, I haven't used it, I just found it a while ago via a reference in the link above.
If you're primarily interested in deployment and you're doing it via a dockerfile, then the answer would be to add composer install and php artisan migrate to your dockerfile so they run when the container is built.
I'm interested in hearing more answers to this. It's something that I'm just getting into as well and would like to learn more about.
I use SSH and run migrations from a terminal inside the container.
I personally like Phusion's approach of using Docker as a 'lightweight virtual machine'. So I used their baseimage-docker which I've extended to create my own Docker image for Laravel applications.
I'm aware Phusion's image can be contentious in the Docker community, and that SSH is frowned upon by some who advocate Docker containers as microservices. But I'm happy with Phusion's approach until there are more established tools and practices for the multi-container approach.
I'm in the process of figuring out creating Docker images for Laravel projects, this is what I have so far.
FROM base_image_with_LAMP_stack_and_dependencies
WORKDIR /var/www/html/app
COPY composer.json composer.json
RUN composer install --no-scripts --no-dev --no-autoloader
COPY . .
RUN echo 'chown -R www-data:www-data /var/www/ \
&& composer dump-autoload \
&& cp .env.example .env \
&& php artisan key:generate \
&& php artisan migrate \
&& apachectl -D FOREGROUND' >> /root/container_init.sh && \
chmod 755 /root/container_init.sh
EXPOSE 80
CMD /root/container_init.sh
This way, there is no dependency on database during build time, and the migration process can run every time a new container is started.

Categories