Docker: run multiple container on same tcp ports with different hostname - docker-compose

Is there a way to run multiple docker containers on the same ports? For example, I have used the ports 80/443 (HTTP), 3306 (TCP/MySQL) and 22 (TCP/SSH) in my docker-compose file. Now I want to run this docker-compose for different hostnames on the same ip address on my machine.
- traffic from example1.com (default public ip) => container1
- traffic from example2.com (default public ip) => container2
I have already found a solution only for the HTTP traffic by using an additional nginx/haproxy as a proxy on my machine. But unfortunately, this can't handle other TCP ports.

This isn't possible in the general (non-HTTP) case.
At a lower level, if I connect to 10.20.30.40:3306, the Linux kernel selects a single process that's listening on that port and sends the request there. You're not allowed to bind(2) a second process to the same port. (This is also why you get an error if you try to docker run -p picking a host port that's already in use.)
In the case of HTTP, there's the further detail that the host-name part of the URL is also sent in an HTTP Host: header: the Web browser both does a DNS lookup for e.g. stackoverflow.com and connects to its IP address, and also sends a Host: stackoverflow.com HTTP header. That's the specific mechanism that lets you run a proxy on port 80, and then forward to some other backend service via a virtual-host setup.
That mechanism is very specific to HTTP, though, and doesn't work for other protocols that don't have support for it. I don't think either MySQL or ssh have similar mechanisms in their wire protocol.
(In the particular situation you describe this is probably relatively easy to handle. You wouldn't want to make either your internal database or an sshd visible publicly, so delete their ports: from your docker-compose.yml file, and then just worry about proxying the HTTP service. It's pretty unusual and a complex setup to run sshd in Docker so you also might remove that and simplify your stack a little.)

Related

Why does MongoDB port 27017 need to be opened in AWS EC2 Security Group?

(I've searched SO, AWS support and more widely without success.)
I've just successfully deployed a MEANjs application to a Bitnami MEAN instance on EC2, following Ahmed Haque's excellent tutorial on scotch.io. As part of the tutorial/deployment I altered the AWS Security Group to include port 27017 for MongoDB traffic. The CIDR notation for the port 27017 was 0.0.0.0/0 - which AFAIK means 'allow access from any IP address'.
Question: Why does MongoDB port 27017 need to be opened in AWS EC2
Security Group for a 'production' type environment? Surely this is directly exposing the DB to the
Internet. The only thing that should be talking to Mongo is the
"/server/api" code, which is running on the same instance -
and so shouldn't need the port opening.
If I change the Security Group rule for port 27017 by closing off 27017, changing the source to: localhost, the internal IP address, the public IP address, or hack a CIDR to be equivalent to any of those - then the web app hangs (static content returns but no responses to db backed api calls). Changing the SG rule back to 0.0.0.0/0 almost immediately 'fixes' the hang.
All is otherwise sweet with my install. I've closed port 3000 (the node app) in the Security Group and am using Apache to proxy port 80 traffic to port 3000. Set up like this, port 3000 does not need to be open in the Security Group; to me this implies that on-instance traffic doesn't need ports to be externally exposed - so how come that's not true of the Mongo port?
I cant see anything in the '/client' code which is talking direct to Mongo.
What am I missing?
Thanks in advance - John
OK, after further investigation and overnight/red wine reflection I think I have an answer for those learners like me following the above tutorial (or similar). Following the Agile principle that 'done' means 'working code in a production environment' I was trying to understand the last 5 meters as a developer trying to get code working in a representative production environment (which wouldn't have unnecessary ports open) - this answer is written from that perspective. (Builds welcome from wiser readers.)
What's Happening
The step in the tutorial which (a) changed the Mongo bind IP address from 127.0.0.1 to 0.0.0.0, and (b) specifies a connection URL which uses the external IP address of the same instance, appears to have two effects:
It makes the MongoDB on the instance you're configuring potentially available to other instances (0.0.0.0 tells Mongo to "listen on all available network interfaces".)
It means that the IP traffic from your MEAN app /server component on the same instance will talk to Mongo as though it was coming from off-instance (even though it's on the same instance). Hence the Security Group needs to make port 27017 open to allow this traffic to flow. (This is the nub of the issue in terms of MEANjs stack component interaction.)
Fix
On a single instance MEANjs server, if you change the Mongo bind IP address back to 127.0.0.1 and the Mongo connection url to be 127.0.0.1:27017 then you can close off port 27017 in the EC2 Security Group and the app still works.
To share one MongoDB across more than one MEANjs app server (without wanting to stray into serverfault territory):
Change the Mongo bind IP address to 0.0.0.0,
Use the private IP address of the Mongo server in other app/instance connection strings
Add a EC2 Security Group CIDR rule of private IP address/24, or private IP address/16 to allow access across instances in the specified internal IP address range.
The above is developer 'hack', not a recommendation for good practice.

Server Connection with public IP

I have setup a simple HTTP java server running locally on port 8000. It simply prints a message "Hello world" when a request comes. When I try to ping it from the browser by running http://localhost:8000/test I get my message printed.
I want to get the same results from another computer that is not local. When I try to use my public IP lets say http:/43.xxx.xxx.xxx:8000/test (even from the same machine) I get an ERR_CONNECTION_REFUSED .
I probably suspect that has something to do with the firewall. Can anyone guide me a little more because I lack the experience?
Thanks in advance
You don't specify what host OS your server/firewall is running so I'll keep this generic...
Without knowing your application, it seems like the server is sending a reset (RST packet) when the first SYN packet shows up indicating that the port (on that interface [your external]) is closed. You can do a quick port scan from here (https://mxtoolbox.com/PortScan.aspx) if you don't have access to a remote machine to test with. Odds are, TCP/8000 will not be open.
If it is, in fact, closed, you'll have to look at the firewall that your host OS is running and find out how to allow TCP/8000 to your host. In a major firewall vendor, your rule would look similar to this:
Source: Any
Destination: Your Public IP Address
Service: TCP/8000
Action: Allow
Logging: Full
That being said, you mentioned this was a PC so look into "iptables" (if you're running *nix) or the Windows Firewall (if you're running Windows) on adding firewall rules (Unfortunately I just joined and can't ask questions/comments, yet).
If you really want to find out what packet is being sent, run a tcpdump on your external interface (let's say eth1) (assuming your remote IP is 1.2.3.4 and your home public IP is 4.5.6.7):
tcpdump -nn -vvv -e -s 0 -X -c 100 -i eth1 host 1.2.3.4 and host
4.5.6.7 and port 8000
Here you're looking for the SYN/SYN-ACK/ACK for a successful TCP negotiation or SYN/RST if there is a firewall rejecting (not dropping) the TCP stream to the port.
Once the port is open on the host OS firewall, take a look at the application to make sure it's configured properly. If this were a standard webserver, you could take a look at the configuration files for the "Allow from" directives to make sure that everyone can access the site. If this is a custom application that you've created, you'll have to check this yourself.
I finally solved my problem. I needed to open a forwarding port in my router that maps my local ip address to the public. My router is TP Link so this what I did:
http://www.tp-link.com/us/faq-72.html
Also in order for this to work every time and not to have to reconfigure this every time I reconected to the router (because I get a new local IP), I have created a static local ip for my server following this guide:
http://www.tp-link.com/us/faq-182.html
Thanks for all the replies.

postgresql-crunchy not in rhc port-forward list

I have installed Postgresql 9.3 on OpenShift with the cartridge available at github. The database is started.
I want to connect to it from PgAdmin-III on my local PC. I am supposed to forward ports with:
rhc port-forward <myapp>
Yet, the list of port forwarding does not contain a forwarding for my Postgresql database. Hence, I cannot configure PgAdmin-III with the local port used for forwarding.
C:\>rhc port-forward ligatures
Checking available ports ... done
Forwarding ports ...
Permission denied - bind(2) while forwarding port 8080. Trying local port 8081
Permission denied - bind(2) while forwarding port 8080. Trying local port 8081
Only one usage of each socket address (protocol/network address/port) is
normally permitted. - bind(2) while forwarding port 8081. Trying local port 8082
Permission denied - bind(2) while forwarding port 8080. Trying local port 8081
Only one usage of each socket address (protocol/network address/port) is
normally permitted. - bind(2) while forwarding port 8081. Trying local port 8082
Only one usage of each socket address (protocol/network address/port) is
normally permitted. - bind(2) while forwarding port 8082. Trying local port 8083
To connect to a service running on OpenShift, use the Local address
Service Local OpenShift
------- -------------- ---- -----------------
haproxy 127.0.0.1:8081 => 127.2.56.130:8080
haproxy 127.0.0.1:8082 => 127.2.56.131:8080
node 127.0.0.1:8083 => 127.2.56.129:8080
Press CTRL-C to terminate port forwarding
How do I get a port forwarding for my postgresql-crunchy database?
Update
I have opened an issue at Bugzilla Redhat.
Update II
Issue can be replicated by creating a simple scalable nodejs + crunchydb application at Openshift.
Looking at the manifest.yml file, it does not look like it is publishing it's list of ports correctly (https://github.com/CrunchyData/openshift-postgres-cartridge/blob/master/metadata/manifest.yml) under the "Publishes" section, which is missing, take a look at this manifest for the official postgresql cartridge and compare the Publishes sections (https://github.com/openshift/origin-server/blob/master/cartridges/openshift-origin-cartridge-postgresql/metadata/manifest.yml)
It also seems to be missing the "protocols" section, along with other important information.
It should also probably use more descriptive port names in the "Endpoints" section. I would recommend logging an issue on that github repo with the specifics of the problem you are encountering.
I was able to run the cartridge just now without any problems. I'll take this offline with the user and try to resolve the problem.

which port is being used by a local web server?

We are using an internal server to host our staging website. I was trying to use browserstack to do compatibility testing on the virtual environment that they provide. In order to setup the virtual environment, I need to specify the port which is being used by the local web server. How can I find out which port is being used by our server? Do I need to go check the settings from the IIS in the server machine?
Web server can run on any port. But the default port is 80. When you type in the URL of a web site the browser uses the default port 80 and connects to it. There are lot of occasions when other ports are used, mostly when more than one web server is needed in the same machine. Like webmin uses port 10000 by default.
For any web server not using port 80 you have to specify the port also with your url like http://yoursite.com:port in case of default webmin install it is like http://localhost:10000
Note:HTTP uses 80 and HTTPS uses 443 by default.
This is documented in their tab for local testing.
Basically you do not need to provide 80 as a port, because it will be used by default.
If the port number is not provided, a default port number of 80 is
used. If the port number is present in the URL, it will be extracted
automatically. To test servers with SSL, check the HTTPS box. Once the
option is checked, you can enter a SSL port number that is independent
of the HTTP port number. When the connection is established, the HTTP
and HTTPS connections appear as separate links.

Connecting to Local Web Server when I am Outside my LAN

I have a web server running out of my home. I have assigned it an address such as 192.168.1.123 on port 80.
I understand that this is running on my local network. If I go to another computer on my network and type in the server's ip address, I can see the server.
Is there a way to access this server from outside my LAN?
Yes, you need to set your router to forward connections to port 80 to your internal IP address (192.168.1.123). Look for Port Forwarding on your router admin screen which I would imagine you access by going to http://192.168.1.1
Keep in mind that your ISP may block port 80 completely in which case you can run your web server on a different port (for example por 8180) and have your router forward connections to port 8180 to your internal IP.
To access your server from outside, you just need to point your browser to your external IP address which you can find out by going to http://www.ipchicken.com
Assuming you have a connection to the internet:
https://github.com/progrium/localtunnel
is a quick way to access your local server from the internet. There might be similar implementations in other languages/platforms. This is just the one I know about.
Remember that security issues need to be carefully considered when opening your local network to the world.
If you use a PHP Webserver you can set it this way:
php -S <YourIPAdresse>:<SomePortNumber> <StartPHPpage>
Example: „php -S 192.168.1.123:9000 index.php"