115

I have a docker-compose yml file as in below

version: '2'
services:
  nodejs:
    build:
      context: .
      dockerfile: DockerFile
    ports:
      - "4000:4000"
    links:
      - redis
    expose:
      - "6379"
  redis:
    build:
      context: .
      dockerfile: Dockerfile-redis

My goal is to forward nodejs-127.0.0.1 port 6379 to the redis host. I can already ping redis from the nodejs machine, but the ports are not mapped. Tried expose options, but no chance either.

Jeff Puckett
  • 37,464
  • 17
  • 118
  • 167
z.a.
  • 2,549
  • 3
  • 12
  • 16

4 Answers4

131

It's important to point out that all of the above solutions map the port to every interface on your machine. This is less than desirable if you have a public IP address, or your machine has an IP on a large network. Your application may be exposed to a much wider audience than you'd hoped.

redis:
  build:
    context:
    dockerfile: Dockerfile-redis
    ports:
    - "127.0.0.1:3901:3901"

127.0.0.1 is the ip address that maps to the hostname localhost on your machine. So now your application is only exposed over that interface and since 127.0.0.1 is only accessible via your machine, you're not exposing your containers to the entire world.

The documentation explains this further and can be found here: https://docs.docker.com/compose/compose-file/#ports


Note: If you're using Docker for mac this will make the container listen on 127.0.0.1 on the Docker for Mac VM and will not be accessible from your localhost. If I recall correctly.

Breedly
  • 12,838
  • 13
  • 59
  • 83
  • 16
    Kudo for the security prevention. – aymericbeaumet Oct 15 '18 at 23:02
  • 5
    It is really important to know that the HOST:PORT mapping does not work in swarm mode. Better than opening the port is to 'expose' the port and then connect to it via the address redis:3901 (this will only be availabe to other containers in the same network) – Simon Zyx Dec 03 '18 at 16:25
  • Do you know if there's a way to specify the host port as an ephemeral port, but still restrict only to 127.0.0.1? I tried `127.0.0.1::6379`, for example, (where 6379 is the container port) but didn't get the expected results. – rfay Mar 20 '19 at 19:26
  • @rfay I tried this and it works for me. "127.0.0.1::6379". – Gatsby Lee Jun 12 '20 at 18:58
111

If you want to bind to the redis port from your nodejs container you will have to expose that port in the redis container:

version: '2'
services:
  nodejs:
    build:
      context: .
      dockerfile: DockerFile
    ports:
      - "4000:4000"
    links:
      - redis

  redis:
    build:
      context: .
      dockerfile: Dockerfile-redis
    expose:
      - "6379"

The expose tag will let you expose ports without publishing them to the host machine, but they will be exposed to the containers networks.

https://docs.docker.com/compose/compose-file/#expose

The ports tag will be mapping the host port with the container port HOST:CONTAINER

https://docs.docker.com/compose/compose-file/#ports

MemAllox
  • 533
  • 5
  • 22
JesusTinoco
  • 11,288
  • 5
  • 30
  • 23
  • 1
    yes I get this part, but the issue is when go for 127.0.0.1:6379 in the nodejs container I get an error. I am looking for an automated way for port forwarding basically. – z.a. Feb 16 '16 at 19:17
  • 7
    Well, this is because they are running at different hosts/containers. Could you check if using `redis:6379` instead of `127.0.0.1:6379` the issue solves? – JesusTinoco Feb 16 '16 at 19:20
  • 1
    yes, that works. i need to learn the port forwarding feature though. – z.a. Feb 16 '16 at 19:30
  • @z.a. I'm going to try port forwarding inside the guest using netcat e.g., https://unix.stackexchange.com/a/101906/55079 – steamer25 Jul 12 '18 at 22:54
  • 1
    @JesusTinoco Thank you! `redis:6379 instead of 127.0.0.1:6379` helped me a lot! – J_Ocampo Nov 26 '18 at 16:47
  • It is really important to know that the HOST:PORT mapping does not work in swarm mode because there 0.0.0.0 is used as the host which means that it is available from any address – Simon Zyx Dec 03 '18 at 16:26
  • How does this work? Does docker-compose up edit your hosts file? – Charles Wood May 09 '22 at 20:59
11

It seems like the other answers here all misunderstood your question. If I understand correctly, you want to make requests to localhost:6379 (the default for redis) and have them be forwarded, automatically, to the same port on your redis container.

https://unix.stackexchange.com/a/101906/38639 helped me get to the right answer.

First, you'll need to install the nc command on your image. On CentOS, this package is called nmap-ncat, so in the example below, just replace this with the appropriate package if you are using a different OS as your base image.

Next, you'll need to tell it to run a certain command each time the container boots up. You can do this using CMD.

# Add this to your Dockerfile
RUN yum install -y --setopt=skip_missing_names_on_install=False nmap-ncat
COPY cmd.sh /usr/local/bin/cmd.sh
RUN chmod +x /usr/local/bin/cmd.sh
CMD ["/usr/local/bin/cmd.sh"]

Finally, we'll need to set up port-forwarding in cmd.sh. I found that nc, even with the -l and -k options, will occasionally terminate when a request is completed, so I'm using a while-loop to ensure that it's always running.

# cmd.sh
#! /usr/bin/env bash

while nc -l -p 6379 -k -c "nc redis 6379" || true; do true; done &

tail -f /dev/null # Or any other command that never exits
Isaac Betesh
  • 2,935
  • 28
  • 37
6

If you want to access redis from the host (127.0.0.1), you have to use the ports command.

redis:
  build:
    context: .
    dockerfile: Dockerfile-redis
    ports:
    - "6379:6379"
Anthon
  • 69,918
  • 32
  • 186
  • 246
  • 1
    that creates circular dependency, which makes sense. I already have that on nodejs – z.a. Feb 16 '16 at 10:44
  • @z.a. I might have misunderstood what you want, I updated my post it now exposes the 6379 to the host (and any other machines on the network unless you have a firewall). – Anthon Feb 16 '16 at 10:58
  • 2
    hmm, that also won't work I am afraid. this is not necessary to expose port to the nodejs container. ports: exposes ports to the actual host machine. I want to map rdis 6379 port to the nodejs 6379 port. – z.a. Feb 16 '16 at 11:23