I can't see inside the container with a vnc - php

I have a script in php that raises an image of docker (havnesvo / slimerjs) and it passes a .js since the slimer needs a js to boot. When I expose the container and try to see inside with vnc send an error: The host refuse the connection. My script look like:
bash
SCRIPT="script.js"
docker run -p 8080:8080 --rm -ti -v `pwd`:/scripts havnesvo/slimerjs bash -c "sed -i 's/640x480x8/1600x1400x8/' /usr/bin/xvfb-run && /usr/bin/slimerjs /scripts/$SCRIPT"
Any suggestion?

Related

Start PHP script when <docker compose up -d> that runs permanently

Is there a way to start a PHP script that starts when the docker containers are started with docker compose up -d?
E.g. if there are two containers: One of them is the PHP-Container and the other one is a MariaDB-Container. The PHP-Script should collect data from an API and save them into the MariaDB-Container when the docker containers are started.
I tried to use
CMD [php script.php]
in the Dockerfile and tried to modify the ENTRYPOINT of the Dockerfile:
COPY start-container /usr/local/bin/start-container
RUN chmod +x /usr/local/bin/start-container
ENTRYPOINT ["start-container"]
I also tried it with wait-for-it following this guide, put the "wait-for-it.sh" in the same folder as the Dockerfile and added following lines to the dockerfile:
COPY wait-for-it.sh wait-for-it.sh
RUN chmod +x wait-for-it.sh
CMD ["./wait-for-it.sh", "mariadb:3306" , "--strict" , "--timeout=60", "start_data_collection.sh"]
I also wrote a bash-script that starts the php script because I was not sure whether the php script can be executed from a dockerfile. But nothing seems to work and I don't know what to do next.
You can simply wait for mysql in your bash script :
while !(mysqladmin ping > /dev/null 2>&1)
do
sleep 3
done
and then call your php script.
You can use --host/--port option on mysqladmin to point to your other container. Be aware that you might need to handle the authentication to the mysql server.
If you don't want to do that, and keep the simple tcp check, you should add a -- like so, if we follow the examples from the github you linked :
CMD ["./wait-for-it.sh", "mariadb:3306" , "--strict" , "--timeout=60", "--", "start_data_collection.sh"]
Because you want to run start_data_collection.sh at the end of wait-for-it.sh, you don't want to pass it as argument to the wait-for-it.sh script

Starting Docker PHP server using CMD makes the host recieve "Connection reset by peer" upon connecting

I have a PHP server that I need to launch in a docker image along a Python service. Both of them need to be in the same image. At first, I wrote the Dockerfile to start the PHP server, by following a simple guide I found online, and I came up with this:
FROM php:7-apache
COPY ./www/ /var/www/html
WORKDIR /var/www/html
EXPOSE 70
Then, because I need a third service running on a second container, I created the following docker-compose file:
version: '3.3'
services:
web:
build: .
image: my-web
ports:
- "70:80"
secondary-service:
image: my-service
ports:
- "8888:8888"
Using only that, the website works just fine (except for the missing service on the web container). However, if I want to start a service inside the web container alongside the web, I need to start the website manually from a bash script, since docker can only have one CMD entry. This is what I tried:
FROM php:7-apache
COPY ./www/ /var/www/html
RUN mkdir "/other_service"
COPY ./other_service /other_service
RUN apt-get update && bash /other_service/install_dependenci172.17.0.1es.sh
WORKDIR /var/www/html
EXPOSE 70
CMD ["bash", "/var/www/html/launch.sh"]
And this is launch.sh:
#!/bin/bash
(cd /other_service && python3 /other_service/start.py &) # CWD needs to be /other_service/
php -S 0.0.0.0:70 -t /var/www/html
And that also starts the server without problems, along with other_service.
However, when I go to my browser (in the host) and browse to http://localhost:70, I get the error "Connection reset". The same happens when I try to do a request using curl localhost:70, which results in curl: (56) Recv failure: Connection reset by peer.
I can see in the log of the web that the php test server is running:
PHP 7.4.30 Development Server (http://0.0.0.0:70) started
And if I open a shell inside the container and I run the curl command inside of it, it gets the webpage without any problems.
I have been searching similar questions around, but none if them had an answer, and the ones that did didn't work.
What is going on? Shouldn't manually starting the server from a bash script work just fine?
Edit: I've just tried to only start the PHP server like below and it doesn't let me connect to the webpage either
#!/bin/bash
#(cd /other_service && python3 /other_service/start.py &) # CWD needs to be /other_service/
php -S 0.0.0.0:70 -t /var/www/html
I found the issue. It was as easy as starting the Apache server too:
#!/bin/bash
(cd /other_service && python3 /other_service/start.py &) # CWD needs to be /other_service/
/etc/init.d/apache2 start
php -S 0.0.0.0:70 -t /var/www/html

newrelic_name_transaction doesn’t work with crons on Docker container

I try to rename transactions with newrelic_name_transaction in crons executed in Docker container but it doesn’t work. It looks like the cron is not catched in NewRelic (on Non Web Transactions)
If I execute the cron directly on SSH on Docker it’s work (I see it on Non Web Transactions with the new name). In any case, the function returns always true.
I have the same problem with the newrelic_custom_metric function.
I have this on my Dockerfile :
RUN
curl -L https://download.newrelic.com/php_agent/release/newrelic-php5-9.20.0.310-linux.tar.gz | tar -C /tmp -zx &&
export NR_INSTALL_USE_CP_NOT_LN=1 &&
export NR_INSTALL_SILENT=1 &&
/tmp/newrelic-php5-/newrelic-install install &&
rm -rf /tmp/newrelic-php5- /tmp/nrinstall* &&
sed -i -e ‘s/“REPLACE_WITH_REAL_KEY”/"[MY KEY]"/’
-e ‘s/newrelic.appname = “PHP Application”/newrelic.appname = “PHP Application”\nnewrelic.attributes.include = request.parameters.*/’
/usr/local/etc/php/conf.d/newrelic.ini
I use this parameters to launch the container :
spec:
restartPolicy: OnFailure
containers:
- name: cron-master
image: [MY IMAGE]
command: ["/bin/sh","-c"]
args:
- gcsfuse --key-file /root/secret/key.json -o allow_other,nonempty,rw --uid 33 --gid 33 goons-catella-prod /var/www/html/web/uploads;
php /var/www/html/bin/console scheduler:execute --env=prod -vvv;
fusermount -u /var/www/html/web/uploads;
It’s the line
php /var/www/html/bin/console scheduler:execute --env=prod -vvv;
that launch crons (it’s the Symfony Bundle jmose/command-scheduler-bundle). When I launch it manually on SSH it’s work.
However, the Agent works perfectly when i go on the website with my browser.
Could you help me please ?
Thanks a lot

Docker environmental variables are not accessible in a PHP web application

index.php:
<?php
$host = getenv('HOST');
$port = getenv('PORT');
echo "HOST is : $host";
echo "PORT is : $port";
?>
Dockerfile:
FROM php:7.4-cli
COPY . /var/www/php
EXPOSE 8000
RUN adduser rouser
CMD ["su", "-", "rouser", "-c", "cd /var/www/php && php -S 0.0.0.0:8000"]
I build a PHP docker image for my application.
docker build -t php-web-app:1.0.0 .
Running my PHP docker container:
docker run -e HOST='0.0.0.0' \
-e PORT='8084' \
-p 8000:8000 \
php-web-app:1.0.0
I made a curl request to my web application, and here the docker environment variable is not accessible by the PHP web application. It seems to be a security feature and how to do we access the docker environmental variable within a php web application.
$ curl http://0.0.0.0:8000/
HOST is : PORT is :
I'm going to guess that changing user does not preserve the environment variables of your execution.
You can check which variables are available in the environment with the env command.
There are however several things that are non-idiomatic going on with your Dockerfile.
You should not create users in your docker image. You can simply set the userid and groupid of your user in the container by setting the --user uid:gid flag in docker run.
You should not run interactive commands such as adduser in a Dockerfile. Unless you can provide all parameters in a single command so that it can run without user-intervention. Adding users is not one of them; how will you provide a password?
So to see the the environment, change your CMD line to the following:
CMD ["su", "-", "rouser", "-c", "env"]
You will see that it prints the following:
SHELL=/bin/bash
PWD=/home/rouser
LOGNAME=rouser
HOME=/home/rouser
USER=rouser
SHLVL=0
PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
MAIL=/var/mail/rouser
_=/usr/bin/env
The environment variables you set are not available. However, if we change the CMD line to just print the env we get another output.
CMD ["env"]
shows us:
HOSTNAME=be0b41fed51e
PHP_INI_DIR=/usr/local/etc/php
PORT=8084
HOME=/root
PHP_LDFLAGS=-Wl,-O1 -pie
PHP_CFLAGS=-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
PHP_MD5=
PHP_VERSION=7.4.6
GPG_KEYS=42670A7FE4D0441C8E4632349E4FDC074A4EF02D 5A52880781F755608BF815FC910DEB46F53EA312
PHP_CPPFLAGS=-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
PHP_ASC_URL=https://www.php.net/distributions/php-7.4.6.tar.xz.asc
PHP_URL=https://www.php.net/distributions/php-7.4.6.tar.xz
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOST=0.0.0.0
PHPIZE_DEPS=autoconf dpkg-dev file g++ gcc libc-dev make pkg-config re2c
PWD=/
PHP_SHA256=d740322f84f63019622b9f369d64ea5ab676547d2bdcf12be77a5a4cffd06832
Notice here that the user is not rouser, but the root user. You can change this by passing, for example, --user 1000:1000 in your docker run command.
So, to fix your problem, I propose you use the following Dockerfile:
FROM php:7.4-cli
COPY . /var/www/php
EXPOSE 8000
# RUN adduser rouser
# CMD ["su", "-", "rouser", "-c", "cd /var/www/php && php -S 0.0.0.0:8000"]
WORKDIR /var/www/php
CMD ["php", "-S", "0.0.0.0:8000"]
Then we get the following output:
$ curl http://0.0.0.0:8000
HOST is : 0.0.0.0PORT is : 8084
If you login to your docker container with
docker exec -it [container id] bash
and run
env
command, you will see that the passed variables are there.
I'm not a PHP expert, but try the same exercise locally (without docker) and see if you are able to print out any env variable via getenv

Starting FOREVER or PM2 as WWW-DATA from a PHP script

I have a nodejs script named script.js.
var util = require('util');
var net = require("net");
process.on("uncaughtException", function(e) {
console.log(e);
});
var proxyPort = "40000";
var serviceHost = "1.2.3.4";
var servicePort = "50000";
net.createServer(function (proxySocket) {
var connected = false;
var buffers = new Array();
var serviceSocket = new net.Socket();
serviceSocket.connect(parseInt(servicePort), serviceHost);
serviceSocket.pipe(proxySocket).pipe(serviceSocket);
proxySocket.on("error", function (e) {
serviceSocket.end();
});
serviceSocket.on("error", function (e) {
console.log("Could not connect to service at host "
+ serviceHost + ', port ' + servicePort);
proxySocket.end();
});
proxySocket.on("close", function(had_error) {
serviceSocket.end();
});
serviceSocket.on("close", function(had_error) {
proxySocket.end();
});
}).listen(proxyPort);
I am runing it normally like nodejs script.js, but now i want to include forever or pm2 functionalities as well. When i am root everything works smootly:
chmod -R 777 /home/nodejs/forever/;
-- give rights
watch -n 0.1 'ps ax | grep forever | grep -v grep'
-- watch forwarders (where i see if a forever is opened)
/usr/local/bin/forever -d -v --pidFile "/home/nodejs/forever/file.pid" --uid 'file' -p '/home/nodejs/forever/' -l '/home/nodejs/forever/file.log' -o '/home/nodejs/forever/file.log' -e '/home/nodejs/forever/file.log' -a start /etc/dynamic_ip/nodejs/proxy.js 41789 1.2.3.4:44481 414 file
-- open with forever
forever list
-- it is there, i can see it
forever stopall
-- kill them all
The problem is when i want to run the script from a PHP script with the system or exec functions :
sudo -u www-data /usr/local/bin/forever -d -v --pidFile "/home/nodejs/forever/file.pid" --uid 'file' -p '/home/nodejs/forever/' -l '/home/nodejs/forever/file.log' -o '/home/nodejs/forever/file.log' -e '/home/nodejs/forever/file.log' -a start /etc/dynamic_ip/nodejs/proxy.js 41789 1.2.3.4:44481 414 file
-- open as www-data (or i can do this just by accessing `http://1.2.3.4/test.php`, it is the same thing)
forever list
-- see if it is there, and it is not (i see it in watch)
forever stopall
-- says no forever is opened
kill PID_ID
-- the only way is to kill it by pid ... and on another server all of this works very well, can create and kill forevers from a php script when accessing it from web ... not know why
-- everything is in /etc/sudoers including /usr/local/bin/forever
Why is that? How can i solve this?
I also made some trick, created a user 'forever2', i created a script.sh with this content :
sudo su forever2 user123; /usr/local/bin/forever -d -v --pidFile "/home/nodejs/forever/file.pid" --uid 'file' -p '/home/nodejs/forever/' -l '/home/nodejs/forever/file.log' -o '/home/nodejs/forever/file.log' -e '/home/nodejs/forever/file.log' -a start /etc/dynamic_ip/nodejs/proxy.js 41789 1.2.3.4:44481 414 file;
where user123 is not existent, is just a trick to exit the shell after execution. The script works, runs forever, i can close all forevers with the command forever stopall from root. When i try the same thing running the http://1.2.3.4/test.php or as www-data user i cannot close it from root or www-data, so not even this works.
I tried from Ubuntu 14.04.3 LTS, Ubuntu 14.04 LTS , Debian GNU/Linux 8 ... still the same thing.
Any ideeas?
Thanks.
If you are starting the process from within Apache or the web-server you are already as the www-data user, so doing a sudo su to the user context you already have is likely not necessary.
When you start this forever task you may also be required to shut the terminals/inputs and directly send to background. Something like this:
// Assemble command
$cmd = '/usr/bin/forever';
$cmd.= ' -d -v --pidfile /tmp/my.pid'; // add other options
$cmd.= ' start';
$cmd.= ' /etc/dynamic_ip/nodejs/proxy.js';
// "magic" to get details
$cmd.= ' 2>&1 1>/tmp/output.log'; // Route STDERR to STDOUT; STDOUT to file
$cmd.= ' &'; // Send whole task to background.
system($cmd);
Now, there won't be any output here but you should have something in /tmp/output.log which could show why forever failed, or the script crashed.
If you've been running the script sometimes as root, then trying the same command as www-data you may also be running into a permissions on one or more files/directories created from the execution as root which now conflict when running as www-data.
This is part of PHP security you say you're running it from a php script and your not your running it from Apache via a php script.
PHP web scripts should not have root access as such they run under the same permissions as Apache user www-data.
There are ways to prevent php running as root but run a task as root but it's a little hacky and I'm not going to share the code but I will explain so you can look into it. here is where to start
http://php.net/manual/en/function.proc-open.php
With a Proccess like this you can then execute a proc. Like your script.js via nodeJS using SUDO and then read stdOut and stdErr wait for password request then provide it by writing to stdIn for that process.
Don't forget in doing this the user www-data has to have a password and be in the sudoers list
Per the OPs Comment
Due to the way SUDO works the PATH does not appear to contain the path to the node executables npm, node so your best of building a .sh (bash script) and using sudo to run that.
You still need to monitor this process as it will still ask for a password
#!/bin/bash
sudo -u ec2-user -i
# change this to the path you want to run from
cd ~
/usr/local/bin/pm2 -v

Categories