How to reverse SSH tunnel to remote docker container for Xdebug? - php

There are many posts on SO and elsewhere on how to set this up. So far I've been unsuccessful in getting it working.
Setup
Local machine - Windows 10, with Cygwin, git bash, and WSL2 with Ubuntu installed; and MacBook Air (Mojave)
Host machine - AWS EC2 instance running Amazon Linux 2
Docker container - CentOS 7.8 running PHP with Xdebug
Goal
Remotely debug PHP code in container from local machine by utilizing a reverse tunnel from the local machine to the container.
I have gotten this working before when the PHP code was installed locally on the host machine, so the question is not around Xdebug. As soon as I moved the PHP code into the container, debugging no longer works.
What I've tried
Setting up a reverse tunnel from the local machine to the host EC2 instance works. For this I'm doing ssh -vvv -i "aws.pem" -R 9000:localhost:9000 user#ec2instance in terminal, cygwin, or git bash and testing with nc -z localhost 9000 || echo 'no tunnel open' on the host machine.
When I docker exec -it container bash into the container and run nc, the tunnel is not available.
I'm using docker-compose:
version: '2'
services:
web:
image: 'privateregistry/project/container:latest'
restart: always
container_name: web
ports:
- '8082:80'
- '447:443'
- '9000:9000'
volumes:
- '.:/var/www/project'
I have tried with and without mapping the 9000 port. I have tried variations of the ssh tunnel:
ssh -vvv -i "aws.pem" -R :9000:localhost:9000 user#ec2instance
ssh -vvv -i "aws.pem" -R 0.0.0.0:9000:localhost:9000 user#ec2instance
ssh -vvv -i "aws.pem" -R \*:9000:localhost:9000 user#ec2instance
ssh -vvv -i "aws.pem" -R 9000:172.20.0.2:9000 user#ec2instance (container IP)
I've also tried using ssh -L with no luck.
Several posts, like this one suggest adding GatewayPorts yes on the host machine. I've tried this as well with no change.
I have not tried using --network=host, primarily due to security concerns. I also would rather not use ngrok, as I'd like to be able to use localhost or host.docker.internal for the xdebug.remote_host setting.
For completeness, here is what I have for Xdebug:
[XDebug]
xdebug.remote_enable=1
xdebug.remote_autostart=1
xdebug.remote_handler="dbgp"
xdebug.remote_port=9000
xdebug.remote_host="host.docker.internal"
;xdebug.remote_connect_back=1
xdebug.idekey = VSCODE
xdebug.remote_log = "/var/log/xdebug.log"

I got this working. After reading up on the ssh man page and looking over things again, I realized I was binding to the docker container IP not the bridge (docker0) IP.
I updated my connect command to ssh -vvv -i "aws.pem" -R 9000:172.17.0.1:9000 user#ec2instance with the right IP and the tunnel started working. I do still have GatewayPorts enabled (per the man page) and removed the 9000:9000 mapping.
I then updated my xdebug.remote_host value to the same IP and debugging is now working. Not sure why host.docker.internal didn't work, but that's for another day.

Related

Create Socket Listener in Docker

I'm a newbie with Docker, but I need a port e.g. (5000) to which I will be able to send any file from the external server and the server should accept it.
I am using Alpine Linux v3.16
i have docker on it
since I've been searching for two days on Google, I tried the following commands on docker:
1.) docker pull appline/socat
2.) iptables -t nat -A DOCKER -p tcp --dport 8001 -j DNAT --to-destination 172.20.0.5:8000
My dockerfile currently looks like this:
FROM php:7.4.9-alpine3.12
#COPY. /usr/src/enterprise-service-bus
WORKDIR /usr/src/enterprise-service-bus
#RUN pecl install apc
COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/bin/
# Install PHP extensions
RUN install-php-extensions ldap bcmath sockets mysqli pdo pdo_mysql pdo_pgsql
EXPOSE 80
CMD ["php", "artisan", "serve", "--host=0.0.0.0", "--port=80"]
To emphasize that on the second server the application is configured to send all files, it is important to assign only the server ip and port to which the file will be forwarded in the configuration.
If you can understand me as a beginner what I need, thank you.
I tried to explain everything I could in this matter.
In case my question is not understandable, I will delete it, I don't know how to explain this better.
Thank you for your understanding.

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Ă  :)

Enter docker container from host using docker-machine

How can I connect to Php container from my Windows machine?
I run docker toolbox https://www.docker.com/products/docker-toolbox on my Windows 10 machine. It's create docker-machine (env default) using virtualbox on port tcp://192.168.99.100:2376 and from host machine (Windows) I can connect to it by ssh. Inside docker-machine I run containers with docker-compose.
I run PhpStorm on Windows and I want to configure PHP interpreter to listen to containerized php. I have read https://confluence.jetbrains.com/display/PhpStorm/Working+with+Remote+PHP+Interpreters+in+PhpStorm but still no sure how to configure it.
I found http://obrown.io/2015/12/23/phpunit-docker-phpstorm.html
The goal create local php script and somehow provide in it connection to php.
In the example author create new container and execute/link php there
End of "docker-machine env default" output
/usr/local/bin/docker run -i --rm -v "${PWD}":"${PWD}" -w ${PWD} --net=host --sig-proxy=true --pid=host originalbrownbear/php:7-cli-phpunit php "$#"
How can I configure such script to use existing docker container with php?
Nornally I enter running container - docker exec -it container_tag_name /bin/bash
And there I can execute php.

docker website opens after a while - ec2/virtualbox

I have created a docker image, tested it locally. All working well.
After that I used the same Dockerfile - built it and run it on EC2.
The Apache webserver is listening to the connections, I have opened firewall in EC2 machine security settings, but if I try to navigate to the webisite, it seems to be opening for approx 2.5 minutes.
And then the website OPENS. Each navigation step takes 2.5 minutes.
Later:
I have tried to replicate this environment on Windows machine with Virtual Box and it has exactly same issue. Website would take long time and eventually open. It also broke connect to another machine that that was completely not docker related (Ubuntu dev box)
Can anybody advice something?
Here is docker file:
FROM ubuntu
RUN apt-get update -y
RUN apt-get install -y apache2 php5 vim libapache2-mod-php5 php5-mcrypt
RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf
ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_LOG_DIR /var/log/apache2
ENV APACHE_LOCK_DIR /var/lock/apache2
ENV APACHE_PID_FILE /var/run/apache2.pid
EXPOSE 80
RUN ln -sf /dev/stderr /var/log/apache2/error.log
CMD /usr/sbin/apache2ctl -D FOREGROUND
As illustrated in "Debug your PHP in Docker with Intellij/PHPStorm and Xdebug", it is possible to debug php from within a container.
The OP activated it directly in php.ini:
[xdebug]
zend_extension="/usr/lib/php5/20121212/xdebug.so"
xdebug.remote_enable=on xdebug.remote_handler=dbgg
xdebug.remote_host=172.17.0.1
xdebug.remote_port=9000
xdebug.remote_connect_back=on
xdebug.remote_autostart=on
xdebug.remote_log="/var/log/xdebug/xdebug.log"
Removing that module was enough to bring the response time down.

Docker with php built-in server

I'm trying to run php built-in server (php -S localhost:8080) via docker, I cannot access site from the host though - I always end up with Connection reset.
Here's a simple Dockerfile I build on:
FROM centos:centos6
RUN rpm -Uvh http://mirror.webtatic.com/yum/el6/latest.rpm
RUN rpm -Uvh http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
RUN rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
RUN yum --enablerepo=remi,remi-php55 install -y php php-opcache php-cli php-pear php-common && yum clean all
RUN php -r "readfile('https://getcomposer.org/installer');" | php
RUN echo "date.timezone = Europe/Prague" >> /etc/php.ini
RUN mv composer.phar /usr/bin/composer
RUN php -r "eval('?>'.file_get_contents('http://backend.bolt80.com/piecrust/install'));"
RUN mv piecrust.phar /usr/bin/chef
CMD ["/bin/bash"]
Is it even possible to run this server with docker? While trying to make it work, I found out that when nginx was installed and set to listen on this very port, it is accessible from the host. PHP built-in server seems to be hidden from the host, thus not able to serve any requests though.
Anyone was successful making this work?
If from within the docker container you start your webserver with php -S localhost:8080 then the webserver will only accept connections originating from the docker container itself.
To be able to communicate with your webserver from the docker host you need to make two changes:
in your Dockerfile, add EXPOSE 8080, or when running the container add -p 8080 to the docker run command line. This will tell the docker host that your container has a program which expects communication on port 8080
start the webserver with php -S 0.0.0.0:8080 so it also accepts connections from outside of the docker container itself
Once you have a container running with those changes, open up a new terminal on the docker host and use the docker ps command to see what port on the docker host is forwarded to port 8080 in the container. For instance:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fbccf4058b07 test:latest "php -S 0.0.0.0:8080 4 minutes ago Up 4 minutes 0.0.0.0:49153->8080/tcp sad_hawking
In this example port 49153 of the docker host is to be used. Then query your webserver to validate you can communicate with it:
$ curl http://localhost:49153
For docker compose
services:
api:
build: ./api
command: php -S 0.0.0.0:80
ports:
- 80:80
with dockerfile, placed in ./api folder
FROM php:apline
WORKDIR /
COPY . .

Categories