Basic Nginx container (static file) - docker

I am trying to do the simplest possible container with Nginx hosting a simple index.html file. But I can't seem to get it working. I must be missing a concept somewhere and I am hoping for a bit of help.
Here is what I am doing:
I have a folder with 2 files in it:
Dockerfile
FROM nginx:1.18.0
WORKDIR /usr/share/nginx/html
COPY index.html ./
index.html
<!DOCTYPE html>
<html>
<head>
<title>Testing</title>
</head>
<body>
<p>Hello Test App</p>
</body>
</html>
First I build the container. From the folder that has the files, I run this command:
docker image build --tag nginx-test:1.0.0 --file ./Dockerfile .
Then I run the container:
docker run -d -p 3737:3737 nginx-test:1.0.0
Then I browse to http://localhost:3737 (I also tried http://localhost:3737/index.html) and chrome shows an ERR_EMPTY_RESPONSE error:
How can I get my index.html file to be hosted in my container?

The problem was with this command:
docker run -d -p 3737:3737 nginx-test:1.0.0
The -p option is selecting the ports. The first port is what will be exposed on the host machine. The second port is what will be used to communicate with the container. By default, nginx uses port 80 (like most web servers).
So changing that command to:
docker run -d -p 3737:80 nginx-test:1.0.0
Causes the rest of the steps in my scenario to work correctly.

Related

Flask application is not exposing to external world in docker

I'm hosting a flask application in docker container through AWS EC2, which will display the contents of the file that is uploaded to it.
I'm facing an strange issue is that my application is not exposing to the external world, but it works on localhost. When I try to hit on my public ip of the machine, it is showing "refused to connect" (Note: Security groups are fine)
docker ps command showing my container is running fine on the expected port number. Can you please let me know how can i resolve it to make it work? Thanks in advance
Docker version 20.10.7, build f0df350
Here is my Dockerfile,
FROM ubuntu:latest
RUN mkdir /testing
WORKDIR /testing
ADD . /testing
RUN apt-get update&&apt-get install -y pip
RUN pip install -r requirements.txt
CMD flask run
In my requirements.txt file, I'm having flask to be installed in docker.
Here is my flask code and html file,
from flask import Flask,render_template,request
app = Flask(__name__)
#app.route("/")
def file():
return render_template("index.html")
#app.route("/upload", methods= ['POST','GET'])
def test():
print("test")
if request.method == 'POST':
print("test3")
file = request.files['File'].read()
return file
if __name__ == "__main__":
app.run(debug=True,host='0.0.0.0')
index.html:
<html>
<body>
<form action = "http://<publiciIPofmachine>:5000/upload" method = "POST" enctype =
"multipart/form-data">
<input type = "file" name = "File" />
<input type = "submit" value = "Submit" />
</form>
</body>
</html>
docker logs:
Serving Flask app 'app' (lazy loading)
Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
Debug mode: on
Running on all addresses.
WARNING: This is a development server. Do not use it in a production deployment.
Running on http://172.17.0.2:5000/ (Press CTRL+C to quit)
Here are my docker commands that is used,
docker build -t <name> .
docker run -d -t -p 5000:80 <imagename>
You have a typo in the docker run command:
Background
That is what docs say:
-p=[] : Publish a container's port or a range of ports to the host
format: ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort | containerPort
Both hostPort and containerPort can be specified as a
range of ports. When specifying ranges for both, the
number of container ports in the range must match the
number of host ports in the range, for example:
-p 1234-1236:1234-1236/tcp
So you are publishing port in format: hostPort:containerPort
Solution
Instead of your code:
docker run -d -t -p 5000:80 <imagename>
You should do
docker run -d -t -p 80:5000 <imagename>
But it's good practice to define the EXPOSE layer in your container :)
The EXPOSE has two roles:
Its kind of documentation, whoever is reading your Dockerfile, they know what port should be exposed.
You can use the --publish-all | -P flag to publish all exposed ports.

How to change the root path in Nginx configuration

I have created a simple HTML application and I was trying to host it using nginx server.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Simple Test Web App!</title>
</head>
<body >
Test Web App!!!
</body>
</html>
Dockerfile
FROM nginx:latest
# Copy files and directories from the application
COPY index.html /usr/share/nginx/html
# Tell Docker we are going to use this port
EXPOSE 8080
Docker build
docker build -t webapp .
Docker run
docker run -p 8080:8080 webapp:latest
I am able to run the application using http://localhost:8080/ URL. But I want to know how we can change root path to http://localhost:8080/webapp URL.. Means it should serves the request from http://localhost:8080/webapp URI as it was doing with http://localhost:8080/
if you want to redirect your HTML page with subdirectory like HTTP://localhost:8080/webapp instead of HTTP://localhost:8080,
for that, you need to create nginx configuration file that redirect your HTML page into your subdirectory URL. in your nginx configuration file you should add following line,
location /htmlsite { root /var/www/htmlsite; try_files $uri $uri/ =404; }

docker COPY is not copying the files

FROM nginx:alpine
EXPOSE 80
COPY . /usr/share/nginx/html
Am trying to run an Angular app with the following docker configuration. It does work, but I can't see the files/directory that was suppose to be copied in that location "/usr/share/nginx/html" which is super confusing. The directory only contains the default index.html nginx created.
Does it store it in memory or something since the files are not there but it does fetch my website properly.
Build:
docker build -t appname .
Run:
docker run -d -p 80:80 appname
It seems like the COPY destination path is not the path on disk server but its the path inside the image of the docker. Which explains why i cant see my files on the server disk.

How to setup mass dynamic virtual hosts in nginx on docker?

How can I setup mass dynamic virtual hosts in nginx As seen here
except using docker as the host machine?
I currently have it setup like this:
# default.conf
server {
root /var/www/html/$http_host;
server_name $http_host;
}
And in my Dockerfile
COPY default.conf /etc/nginx/sites-enabled/default.conf
And after I build the image and run it:
docker run -d 80:80 -v www/:/var/www/html
But when I point a new domain (example.dev) in my hosts file and make a www/example.dev/index.html. It doesn't work at all.
The setup is correct and it works as i tested on my system. The only issue is that you are copying the file on a wrong path. The docker image doesn't use the sites-enabled path by default. The default config loads everything present in /etc/nginx/conf.d. So you need to copy to that path and rest all works great
COPY default.conf /etc/nginx/conf.d/default.conf
Make sure to map you volumes correctly. While testing I tested it using below docker command
docker run -p 80:80 -v $PWD/www/:/var/www/html -v $PWD/default.conf:/etc/nginx/conf.d/default.conf nginx
Below is the output on command line
vagrant#vagrant:~/test/www$ mkdir dev.tarunlalwani.com
vagrant#vagrant:~/test/www$ cd dev.tarunlalwani.com/
vagrant#vagrant:~/test/www/dev.tarunlalwani.com$ vim index.html
vagrant#vagrant:~/test/www/dev.tarunlalwani.com$ cat index.html
<h1>This is a test</h1>
Output on browser

Docker copy files to and mount same folder

I am working on 'tomcat:7.0.75-jre8-alpine' base image and want to deploy my web application alongwith its configurations file. Below is what I am doing in Dockerfile:
......
COPY <my-app-configurations> /org/app/data
COPY <my-app-configurations> /org/app/conf
......
CMD ["catalina.sh", "run"]
And I am using below command to create a container from above image:
$ docker run -p 8080:8080 -v "/c/Users/jaffy/app:/org/app" myapp-image
'/c/Users/jaffy/app' folder is initially empty and I want to get all contents of '/org/app' in it and remains in-sync.
Initially, all configurations are copied in '/org/app' folder but when '/c/Users/jaffy/app' is mounted, '/org/app' gets cleaned/emptied.
How can I solve this issue that host machine folder remains empty initially but afterwards it reflects the exact state of container's '/org/app' folder and its sub-directories.
Thanks a lot in advance.
There is no way to keep the container's folder content when you mount/share a volume over that folder, because the command is replacing the folder not merging it.
If you don't need to replace all the files in the folder you could just mount the file that need to be changed like:
$ docker run -p 8080:8080 -v "/c/Users/jaffy/app/web.xml:/org/app/web.xml" my-app-image

Resources