gitlab-ci.yml
cache:
key: "$CI_COMMIT_REF_NAME node:14.4.0-alpine"
paths:
- node_modules/
stages:
- release
- deploy
variables:
TAGGED_IMAGE: "$CI_REGISTRY_IMAGE:latest"
.release:
stage: release
image: docker:19.03.12
services:
- docker:dind
variables:
DOCKER_DRIVER: overlay2
DOCKER_BUILDKIT: 1
before_script:
- docker version
- docker info
- echo "$CI_JOB_TOKEN" | docker login --username $CI_REGISTRY_USER --password-stdin $CI_REGISTRY
script:
- printf "REACT_APP_XXX_BACKEND_URI=$REACT_APP_XXX_BACKEND_URI" > .env
- docker build --pull --target $CI_COMMIT_REF_NAME --tag $TAGGED_IMAGE --cache-from $TAGGED_IMAGE .
- docker push $TAGGED_IMAGE
after_script:
- docker logout $CI_REGISTRY
.deploy:
stage: deploy
image: gitlab/dind:latest
services:
- docker:dind
variables:
DOCKER_COMPOSE_PATH: "~/docker-composes/$CI_PROJECT_PATH/docker-compose.yml"
before_script:
- 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
- eval $(ssh-agent -s)
- echo "$DEPLOY_SERVER_PRIVATE_KEY" | tr -d '\r' | ssh-add -
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- ssh-keyscan $DEPLOYMENT_SERVER_IP >> ~/.ssh/known_hosts
- chmod 644 ~/.ssh/known_hosts
script:
- rsync -avR --rsync-path="mkdir -p ~/docker-composes/$CI_PROJECT_PATH/; rsync" ./docker-compose.yml root@$DEPLOYMENT_SERVER_IP:~/docker-composes/$CI_PROJECT_PATH/
- ssh root@$DEPLOYMENT_SERVER_IP "echo "$CI_REGISTRY_PASSWORD" | docker login --username $CI_REGISTRY_USER --password-stdin $CI_REGISTRY; docker-compose -f $DOCKER_COMPOSE_PATH rm -f -s -v $CI_COMMIT_REF_NAME; docker pull $TAGGED_IMAGE; docker-compose -f $DOCKER_COMPOSE_PATH -p $CI_COMMIT_REF_NAME up -d $CI_COMMIT_REF_NAME;"
release_stage:
extends: .release
only:
- stage
environment:
name: staging
url: http://staging.xxx.us
deploy_stage:
extends: .deploy
only:
- stage
environment:
name: staging
url: http://staging.xxx.us
Dockerfile
# pull official base image
# dev stage
FROM node:14.4.0-alpine AS dev
# set working directory
WORKDIR /var/www/
# install app dependencies
COPY package.json package-lock.json ./
RUN npm ci --silent
# add app
COPY . ./
# builder stage
FROM dev AS builder
RUN npm run build:app
# stage stage
FROM nginx:1.19.1-alpine AS stage
# Remove default files created by Nginx
RUN rm -rvf /usr/share/nginx/html/*
RUN rm -vf /etc/nginx/conf.d/default.conf
COPY --from=builder /var/www/build/ /usr/share/nginx/html
CMD ["nginx-debug", "-g", "daemon off;"]
docker-compose.yml
version: '3.8'
services:
stage:
container_name: xxx-website-stage
image: registry.gitlab.com/xxx.us/website:latest
build:
context: .
target: stage
dockerfile: Dockerfile
ports:
- '3002:80'
restart: always
default.conf
upstream staging-xxx-us {
server 0.0.0.0:3002;
}
server {
listen 3002;
server_name localhost;
# ...
}
server {
listen 80;
server_name staging.xxx.us;
location / {
proxy_pass http://staging-xxx-us;
proxy_http_version 1.1;
proxy_cache_bypass $http_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
}
}
sudo docker ps
... ... "/docker-entrypoint.…" ... ... 0.0.0.0:3002->80/tcp xxx-website-stage
sudo ufw status numbered
Status: active
To Action From
-- ------ ----
[ 1] OpenSSH ALLOW IN Anywhere
[ 2] 22/tcp ALLOW IN Anywhere
[ 3] 80/tcp ALLOW IN Anywhere
[ 4] 443/tcp ALLOW IN Anywhere
[ 5] OpenSSH (v6) ALLOW IN Anywhere (v6)
[ 6] 22/tcp (v6) ALLOW IN Anywhere (v6)
[ 7] 80/tcp (v6) ALLOW IN Anywhere (v6)
[ 8] 443/tcp (v6) ALLOW IN Anywhere (v6)
sudo netstat -ltnp | grep :*
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 12088/nginx: master
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN 680/systemd-resolve
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1534/sshd
tcp6 0 0 :::80 :::* LISTEN 12088/nginx: master
tcp6 0 0 :::22 :::* LISTEN 1534/sshd
tcp6 0 0 :::3002 :::* LISTEN 28198/docker-proxy
sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Everything works fine with port 3001, but nothing works with any other ports (e.g. 3002). I modify ports in docker-compose.yml to <anything>:80 and default.conf to point to <anything> in the upstream block.
Update 2
I have access to the container using docker exec and the website opens with the port 3002, I mean http://staging.xxx.us:3002 works fine, but I expect users open the website without any specific port, I mean http://staging.xxx.us
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.
Hi there @meness,
Are you running the 3001 and 3002 applications on the same server?
I think that you are trying to start 2 instances of the Nginx container on port 80, one for your 3001 app and one for the 3002 app.
Can you run docker ps -a and share the output here to verify if this is the case?
If this is the case, what you would need to do is adjust the CI/CD process so that you don’t spin up 2 instances of the Nginx container on the same port, but just spin up 1 instance with multiple server blocks for each backend application.
Let me know how it goes1 Regards, Bobby
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
Full documentation for every DigitalOcean product.
The Wave has everything you need to know about building a business, from raising funding to marketing your product.
Scale up as you grow — whether you're running one virtual machine or ten thousand.

From GPU-powered inference and Kubernetes to managed databases and storage, get everything you need to build, scale, and deploy intelligent applications.
