27

I am a docker beginner and the first thing i did was download nginx and tried to mount it on 80:80 port but Apache is already sitting there.

docker container run --publish 80:80 nginx

and docker container run --publish 3000:3000 nginx

I tried doing it like this 3000:3000 to use it on port 3000 but it doesn't work .And it doesn't log anything either which i could use for referance.

Mayank Singh Fartiyal
  • 867
  • 1
  • 11
  • 26

5 Answers5

50

The accepted answer does not change the actual port that nginx is starting up on.

If you want to change the port nginx starts up on inside the container, you have to modify the /etc/nginx/nginx.conf file inside the container.

For example, to start on port 9080:

Dockerfile

FROM nginx:1.17-alpine
COPY <your static content> /usr/share/nginx/html
COPY nginx.conf /etc/nginx/
EXPOSE 9080
CMD ["nginx", "-g", "daemon off;"]

nginx.conf

# on alpine, copy to /etc/nginx/nginx.conf
user                            root;
worker_processes                auto;

error_log                       /var/log/nginx/error.log warn;

events {
    worker_connections          1024;
}

http {
    include                     /etc/nginx/mime.types;
    default_type                application/octet-stream;
    sendfile                    off;
    access_log                  off;
    keepalive_timeout           3000;
    server {
        listen                  9080;
        root                    /usr/share/nginx/html;
        index                   index.html;
        server_name             localhost;
        client_max_body_size    16m;
    }
}

Now to access the server from your computer:

docker build . -t my-app
docker run -p 3333:9080 my-app

navigating to localhost:3333 in a browser, you'll see your content.

There is probably a way to include the default nginx.conf, and override only the server.listen = PORT property, but I'm not too familiar with nginx config, so I just overwrote the entire default configuration.

Engineero
  • 12,340
  • 5
  • 53
  • 75
mancini0
  • 4,285
  • 1
  • 29
  • 31
  • where did your `nginx` come from, and what does it do? – PositiveGuy Sep 11 '20 at 23:31
  • 1
    @PositiveGuy nginx.conf is a configuration file that you keep under source control - in your dockerfile you instruct docker to copy the nginx.conf file over from your source code directory to the nginx container at the path /etc/nginx/nginx.conf, as that is the default place nginx looks for configuration. In other words, nginx.conf is at the same level as your Dockerfile. – mancini0 Sep 11 '20 at 23:52
  • maybe just don't use root user. You could also use already non root nginx-images like nginxinc/nginx-unprivileged – tuxErrante Apr 19 '21 at 11:01
  • 4
    To keep this post up to date. On new NGINX versions the `nginx.conf` file has moved to this location `/etc/nginx/conf.d/default.conf`. So copying a custom nginx.conf file could be like this `COPY ["default.conf", "/etc/nginx/conf.d/default.conf"]`. Assuming the user does not want to add another file only overwriting the default. – Thanos Oct 13 '21 at 07:36
25

When you're starting with Docker you may find helpful information about images at DockerHub. For example with nginx you have a section about how to expose public ports.

You can just use:

docker run --publish 3000:80 nginx

Port 3000 in your localhost will be forwarded to port 80 which is the port that nginx images use to wait for http connections.

I also recommend you to read these official docs about networking in Docker.

Miguel A. C.
  • 555
  • 6
  • 11
7

You wrote you are a beginner, so first of all I'll just mention that the default configuration for the nginx image (I'll assume you're using a standard image) is to listen in port 80.
This is why you can't map to port 3000 inside the container because there is no process that listen to this port.

Now if I understood you correctly and with the fact that you're using nginx with docker I guess you want to be able to configure the container's port (and not the host port because this is quiet trivial).

@mancini0 started a good direction, but I'll show how to do it in a more dynamic fashion.

We'll use the envsubst command which substitutes environment variables in shell format strings.
This command is available with the offical nginx image and also with the alpine version.

Now for the solution.

Step #1
write your nginx configuration in a template file - let's call it: site.template:

server {
    listen       ${PORT};
    server_name  localhost;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
}

Notice the PORT placeholder.

Step #2 - with docker-compose
Mount that inside the /etc/nginx/conf.d directory and then execute the envsubst command to use the template as a reference for default.conf which is the file which will be used to setup the port configuration inside the container:

web:
  image: nginx:alpine
  volumes:
   - ./site.template:/etc/nginx/conf.d/site.template
  ports:
   - "3000:8080"
  environment:
   - PORT=8080
  command: /bin/sh -c "envsubst < /etc/nginx/conf.d/site.template > /etc/nginx/conf.d/default.conf && exec nginx -g 'daemon off;'"

Notice that:
1. You need to execute the nginx daemon after that.
2. I used /bin/sh and not /bin/bash because my base image is alpine.


Step #2 (Another option) - inline docker run
If, for some reason you don't want to work with docker-compose you can use the following bash script:

#!/usr/bin/env bash

##### Variables #####
PORT=8080 #Or $1 if you pass it from command line
TEMPLATE_DIR=$(pwd)/site.template
TEMPLATE_REMOTE_DIR=/etc/nginx/conf.d/site.template
IMAGE_NAME=nginx:alpine

echo "Starting nginx on port: $PORT ..."

##### The docker command #####
docker run -p 3000:$PORT -v $TEMPLATE_DIR:$TEMPLATE_REMOTE_DIR $IMAGE_NAME \
/bin/sh -c "envsubst < $TEMPLATE_REMOTE_DIR > /etc/nginx/conf.d/default.conf && exec nginx -g 'daemon off;'"

(*) You can also write it inside your Dockerfile with the CMD command, but I won't recommend you doing that.

Rot-man
  • 18,045
  • 12
  • 118
  • 124
  • can't you just expose the port in the dockerfile with "ENV NGINX_PORT 8080"? – tuxErrante Apr 19 '21 at 11:03
  • From here: https://docs.docker.com/engine/reference/builder/#expose The EXPOSE instruction does not actually publish the port. It functions as a type of documentation between the person who builds the image and the person who runs the container, about which ports are intended to be published. – Rot-man Apr 19 '21 at 15:57
  • I've written ENV not EXPOSE – tuxErrante Apr 20 '21 at 07:27
  • Sorry (: I think it is more flexible to add it in the docker-compose.yaml (like I did) then hardcoding it in the image. – Rot-man Apr 20 '21 at 08:47
5

You can use nginx.conf to change it to any port.

nginx.conf will have all the configurations related to nginx. Default value for port here is 80 which we can change as below.

nginx.conf

server {
  listen 3000;

  location / {
    root /usr/share/nginx/html;
    index index.html index.htm;
    try_files $uri $uri/ /index.html =404;
  }

  include /etc/nginx/extra-conf.d/*.conf;
}

and in DockerFile add a line:

COPY ./nginx.conf /etc/nginx/conf.d/default.conf
Sushanth
  • 51
  • 2
  • 5
  • 1
    Please explain how your post is providing any new help. The other answers seem to point at the same, but with more information and explanation. Which answer would you prefer? – FrankM Apr 01 '21 at 12:00
  • 1
    It is straight forward answer if we are using DockerFile – Sushanth Apr 15 '21 at 05:13
-1
docker run -e NGINX_PORT=8080 nginx:latest -d 

The page

betelgeuse
  • 1,136
  • 3
  • 13
  • 25
  • 2
    This is inaccurate and simply won't work: the page you are linking explicitly mentions you need some templates to get the NGINX_PORT variable picked up and replaced in those templates. – Clorichel Oct 10 '22 at 06:23