Search code examples
dockeramazon-ec2bitbucket-pipelinesaws-sdk-nodejs

How do I allow access to the docker container on an EC2 instance


I have a build process that looks like this:

1. Code Pushed to BitBucket which is picked up by BitBucker Pipelines

image: node:8.2.1
pipelines:
  default:
    - step:
        name: Push Server to AWS Repository
        script:
          - docker login -u AWS -p $AWS_ECR_LOGIN https://$AWS_ECR_URL
          - docker build -t dev .
          - docker tag dev:latest $AWS_ECR_URL/dev:latest
          - docker push $AWS_ECR_URL/dev:latest

options:
  docker: true

2. BitBucket Pipelines Builds the Docker Image from the Dockerfile in the repo and pushes it to Amazon ECR

# BUILD DEV IMAGE and TEST
FROM node:8.2.1 as builder
COPY ./ /user/src/app
WORKDIR /user/src/app
RUN npm install -g grunt-cli --quiet
RUN npm install --quiet
RUN grunt build
# RUN npm test:build

# BUILD APP IMAGE
FROM node:8.2.1
COPY --from=builder /user/src/app/dist /user/src/app/
WORKDIR /user/src/app
RUN npm install -g mongodb-migrations --quiet
RUN npm install --only=prod --quiet
EXPOSE 5000
CMD npm start

3. Jenkins job watches for the new images in ECR and remotely triggers an EC2 instance to pull and restart the docker image

let dockerApi = new Docker({
    host: DockerIpAddress,
    port: process.env.DOCKER_PORT || 2375,
    version: 'v1.32' // required when Docker >= v1.13, https://docs.docker.com/engine/api/version-history/
});

dockerApi.createContainer({
    Image: IMAGE_NAME,
    AttachStdout: true,
    AttachStderr: true,
    Tty: true,
    Env: [`NODE_ENV=${ENV}`],
    ExposedPorts: {
        "5000/tcp": {},
    },
    HostConfig:{
        PortBindings: {
            "5000/tcp": [{
                "HostPort": "5000"
            }],
        },
    },
})

Problem

Up until this point - everything is working! My docker container is running on the ec2 instance. What's not working is that I can't receive any connections. Even from ssh'd into the ec2 instance, curl http://localhost:5000 won't work. Accessing the ec2 instance from a browser via the public ip or public host doesn't work either.

IP Tables

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy DROP)
target     prot opt source               destination
DOCKER-ISOLATION  all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
DOCKER     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain DOCKER (1 references)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             ip-172-17-0-2.ec2.internal  tcp dpt:5000

Chain DOCKER-ISOLATION (1 references)
target     prot opt source               destination
RETURN     all  --  anywhere             anywhere

Sysctl

$ sysctl net.ipv4.conf.all.forwarding
net.ipv4.conf.all.forwarding = 1

Node Server in Docker Last Line of Output

Server running at: http://localhost:5000

Solution

  • Check that the Dockerfile you're using for creating the image runs a script which expose the server in 0.0.0.0 and not in localhost.

    You should be opening 0.0.0.0:5000->5000 and not run in localhost!!

    Hope this helps.