I have a flask app running in AWS ec2 inside a docker container and I am having latency problems. I figured this is because inside the container, localhost routes to both ipv4's 127.0.0.1 and ipv6's ::1 (based on some other SO posts). I found this blog post which addresses the issue exactly. But in the blog he uses nginx, which I've never used before. He has an nginx config file:
location / { try_files $uri #project; }
location #project {
include uwsgi_params;
uwsgi_pass unix:/tmp/uwsgi.sock;
}
and I'm not sure how I can place this in the container so that it reads properly. I read somewhere that it goes in /etc/nginx, but then how do I edit the dockerfile to include this conf there?
This is the Dockerfile he suggests. Is the line ADD nginx /etc/nginx where the file is getting copied in? and he just didn't give the file an extension?
FROM ubuntu:14.04
RUN apt-get update && apt-get install -y build-essential nginx python3.4 python3.4-dev
RUN easy_install3 pip
WORKDIR /project
ADD requirements.txt /project/requirements.txt
RUN pip install -r requirements.txt
ADD . /project
ADD nginx /etc/nginx
CMD uwsgi -s /tmp/uwsgi.sock -w project:app --chown-socket=www-data:www-data --enable-threads & \
nginx -g 'daemon off;'
Yes, he is adding the file nginx to the container file system location /etc/nginx/
Personally I'd name the file nginx.conf as that is the default name according to the nginx documentation.
By default, the configuration file is named nginx.conf and placed in
the directory /usr/local/nginx/conf, /etc/nginx, or
/usr/local/etc/nginx.
Also, I'd recommend using COPY in stead of ADD according to the Best practices for writing Dockerfiles
For other items (files, directories) that do not require ADD’s tar
auto-extraction capability, you should always use COPY.
To make this work you'll need to install nginx on the container you're running flask on.
Related
I'm trying to create a reverse proxy using nginx running in docker. I have set up the nginx.conf file and it's running fine locally. However, I don't know how to set up the nginx docker with this changed nginx.conf file. Is there any way to do this?
Update: I have been able to change the nginx.conf file inside Docker. However, going to localhost:80/go returns a 502 Bad Gateway. I have a go app running on port 8081 using go run main.go and a python app running on port 8080 using flask run. I'm on a Manjaro VM.
This is the server part of the nginx.conf file
server {
listen 80;
location / {
return 200 'hey there, welcome to our amazing app :)';
}
location /cbl {
proxy_pass http://127.0.0.1:8080;
}
location /go {
proxy_pass http://127.0.0.1:8081;
}
}
And this is the Dockerfile
FROM nginx
RUN mv /etc/nginx/nginx.conf /etc/nginx/nginxorig.conf
#RUN pwd
#RUN cp /home/shark/hwr-nginx/nginx.conf /etc/nginx/conf.d/default.conf
VOLUME /usr/share/nginx/html
VOLUME /etc/nginx
How do I fix this?
[shark#shark-virtualbox hwr-nginx]$ sudo docker build . -t nginx
Sending build context to Docker daemon 7.168kB
Step 1/3 : FROM nginx
---> 7084cd82dcbb
Step 2/3 : RUN mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf_orig
---> Running in 80e011c5b125
mv: cannot stat '/etc/nginx/nginx.conf': No such file or directory
The command '/bin/sh -c mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf_orig' returned a non-zero code: 1
[shark#shark-virtualbox hwr-nginx]$ cat Dockerfile
FROM nginx
RUN mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf_orig
RUN cp hwr-nginx/nginx.conf /etc/nginx/nginx.conf
```` RUN mv and RUN cp are also not working for me :(.
You need to copy your nginx.conf to your container:
For example: COPY conf /etc/nginx
Docs here: https://docs.nginx.com/nginx/admin-guide/installing-nginx/installing-nginx-docker/#managing-content-and-configuration-files
In your Dockerfile, add an instruction to copy your project's reverse proxy configured ngxin.conf into the docker image you intend to build, in the location where nginx will look for its configurations. For example, assuming your base image is Debian, you could do the following in your Dockerfile:
# Move the default conf out of the way
RUN mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf_orig
# Copy in your project's new nginx conf
RUN cp my_project/nginx.conf /etc/nginx/nginx.conf
I have build a dockerfile. My custom nginx conf (nginx.conf) is in root directory
FROM tiangolo/uwsgi-nginx:python3.8-alpine
RUN apk add py3-setuptools
RUN apk add python3-dev
RUN apk add gcc
RUN apk add g++
RUN apk add --no-cache libressl-dev curl-dev musl-dev libffi-dev make
ARG env
WORKDIR /app
COPY ./pip_req.txt /app
RUN pip install -r /app/pip_req.txt
COPY ./ /app
ENV UWSGI_INI /app/deployment/$env/uwsgi.ini
RUN rm /etc/nginx/conf.d/default.conf
COPY deployment/$env/supervisor.conf /etc/supervisor.d/app.ini
COPY deployment/$env/nginx.conf /etc/nginx/conf.d/nginx.conf
On docker image deployment, I get default content in /etc/nginx/conf.d/nginx.conf
server {
listen 80;
location / {
include uwsgi_params;
uwsgi_pass unix:///tmp/uwsgi.sock;
}
}
If I copy nginx.conf with another name, file copies correctly, But i am not sure which conf is being used as both conf use same listen port.
The image you're using has a custom entrypoint script that completely rewrites the Nginx configuration at startup time. There is some minimal ability to customize it through environment variables, or it looks like if you have an /app/nginx.conf file that gets copied to /etc/nginx/nginx.conf and other files are left unmodified. If you do have other files in /etc/nginx/conf.d, they're documented to be used in addition to this default generated documentation.
This image's setup to run two separate processes in a single container isn't generally considered a Docker best practice. You also might consider running a custom image based on the standard python image and a separate nginx proxy container, maybe using Docker Compose to launch them together. The standard nginx image has a fixed default configuration that can be overridden much more normally (either COPYing it into a derived image or with a bind mount); the only particular special setup it has is the ability to replace environment variables.
I am currently running into a problem trying to set up nginx:alpine in Openshift.
My build runs just fine but I am not able to deploy with permission being denied with the following error
2019/01/25 06:30:54 [emerg] 1#1: mkdir() "/var/cache/nginx/client_temp" failed (13: Permission denied)
nginx: [emerg] mkdir() "/var/cache/nginx/client_temp" failed (13: Permission denied)
Now I know Openshift is a bit tricky when it comes to permissions as the container is running without root privilidges and the UID is gerenated on runetime which means it's not available in /etc/passwd. But the user is part of the group root. Now how this is supposed to be handled is being described here
https://docs.openshift.com/container-platform/3.3/creating_images/guidelines.html#openshift-container-platform-specific-guidelines
I even went further and made the whole /var completely accessible (777) for testing purposes but I still get the error. This is what my Dockerfile looks like
Dockerfile
FROM nginx:alpine
#Configure proxy settings
ENV HTTP_PROXY=http://my.proxy:port
ENV HTTPS_PROXY=http://my.proxy:port
ENV HTTP_PROXY_AUTH=basic:*:username:password
WORKDIR /app
COPY . .
# Install node.js
RUN apk update && \
apk add nodejs npm python make curl g++
# Build Application
RUN npm install
RUN ./node_modules/#angular/cli/bin/ng build
COPY ./dist/my-app /usr/share/nginx/html
# Configure NGINX
COPY ./openshift/nginx/nginx.conf /etc/nginx/nginx.conf
COPY ./openshift/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf
RUN chgrp -R root /var/cache/nginx /var/run /var/log/nginx && \
chmod -R 777 /var
RUN sed -i.bak 's/^user/#user/' /etc/nginx/nginx.conf
EXPOSE 8080
It's funny that this approach just seems to effekt the alpine version of nginx. nginx:latest (based on debian I think) has no issues and the way to set it up described here
https://torstenwalter.de/openshift/nginx/2017/08/04/nginx-on-openshift.html
works. (but i am having some other issues with that build so I switched to alpine)
Any ideas why this is still not working?
I was using openshift, with limited permissions, so I fixed this problem by using the following nginx image (rather than nginx:latest)
FROM nginxinc/nginx-unprivileged
To resolve this. I think the Problem in this Dockerfile was that I used the COPY command to move my build and that did not exist. So here is my working
Dockerfile
FROM nginx:alpine
LABEL maintainer="ReliefMelone"
WORKDIR /app
COPY . .
# Install node.js
RUN apk update && \
apk add nodejs npm python make curl g++
# Build Application
RUN npm install
RUN ./node_modules/#angular/cli/bin/ng build --configuration=${BUILD_CONFIG}
RUN cp -r ./dist/. /usr/share/nginx/html
# Configure NGINX
COPY ./openshift/nginx/nginx.conf /etc/nginx/nginx.conf
COPY ./openshift/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf
RUN chgrp -R root /var/cache/nginx /var/run /var/log/nginx && \
chmod -R 770 /var/cache/nginx /var/run /var/log/nginx
EXPOSE 8080
CMD ["nginx", "-g", "daemon off;"]
Note that under the Build Application section I now do
RUN cp -r ./dist/. /usr/share/nginx/html
instead of
COPY ./dist/my-app /usr/share/nginx/html
The copy will not work as I previously ran the ng build inside of the container the dist will only exist in the container as well, so I need to execute the copy command inside of that container
Had the same error on my nginx:alpine Dockerfile
There is already a user called nginx in the nginx:alpine image. My guess is that it's cleaner to use it to run nginx.
Here is how I resolved it:
Set the owner of /var/cache/nginx to nginx (user 101, group 101)
Create a /var/run/nginx.pid and set the owner to nginx as well
Copy all the files to the image using --chown=nginx:nginx
FROM nginx:alpine
RUN touch /var/run/nginx.pid && \
chown -R nginx:nginx /var/cache/nginx /var/run/nginx.pid
USER nginx
COPY --chown=nginx:nginx my/html/files /usr/share/nginx/html
COPY --chown=nginx:nginx config/myapp/default.conf /etc/nginx/conf.d/default.conf
...
If you're here because you failed to deploy an example helm chart (e.g: helm create mychart), do just like #quasipolynomial suggested but instead change your deployment file pull the right image.
i.e
containters:
- image: nginxinc/nginx-unprivileged
more info on the official unprivileged image: https://github.com/nginxinc/docker-nginx-unprivileged
You may change the folder using the nginx.conf file. You can read more information in the section Running nginx as a non-root user.
May or may not be a step in the right direction (especially helpful for those who came here looking for general help on the [emerg] mkdir() ... failed error).
This solution counts from Builing nginx from source.
It took me about seven hours to realize the solution is directly related to the prefix path set in compiling nginx.
This is where my configuration throws off nginx (as a very brief example), compiled from this nginx source:
sudo ./auto/configure \
--prefix=/usr/local/nginx \
--http-client-body-temp-path=/tmp/nginx/client-body-temp \
--http-fastcgi-temp-path=/var/tmp/nginx/fastcgi_temp
Without realizing it, I was setting the prefix to /usr/local/nginx but setting the client body temp path & fastcgi temp path to a directory inside /tmp/nginx.
It's basically breaking nginx's ability to access the correct files, because the temp paths are not correlated to the prefix path.
So I fixed it by (again, super simple configure as an example):
sudo ./auto/configure \
--prefix=/usr/local/nginx \
--http-client-body-temp-path=/usr/local/nginx/client_body_temp \
--http-fastcgi-temp-path=/usr/local/nginx/fastcgi_temp \
Further simplified:
sudo ./auto/configure \
--prefix=/usr/local/nginx \
--http-client-body-temp-path=/client_body_temp \
--http-fastcgi-temp-path=/fastcgi_temp \
Again, not guaranteed to work, but definitely a step in the right direction.
run the below command to fix the above issue. The anyuid security context constraint required.
oc adm policy add-scc-to-user anyuid system:serviceaccount:<NAMESPACE>:default
I'd like to have a lean Docker image for nginx with the Lua module enabled. How can I create this based on Alpine linux?
Here is a Dockerfile:
FROM alpine:3.6
RUN apk add --no-cache nginx-mod-http-lua
# Delete default config
RUN rm -r /etc/nginx/conf.d && rm /etc/nginx/nginx.conf
# Create folder for PID file
RUN mkdir -p /run/nginx
# Add our nginx conf
COPY ./nginx.conf /etc/nginx/nginx.conf
CMD ["nginx"]
Installing the nginx-mod-http-lua package will also install nginx and luajit, among others.
The nginx.conf should contain at least this:
load_module /usr/lib/nginx/modules/ndk_http_module.so;
load_module /usr/lib/nginx/modules/ngx_http_lua_module.so;
pcre_jit on;
events {
worker_connections 1024;
}
daemon off;
Dockerfile:
FROM nginx:1.15-alpine
RUN mkdir -p /run/nginx
RUN apk add --no-cache nginx-mod-http-lua
COPY nginx_conf/ /etc/nginx/ # Your nginx conf
COPY lua/ /etc/lua/ # Your lua files
First line of nginx conf:
load_module /usr/lib/nginx/modules/ndk_http_module.so;
load_module /usr/lib/nginx/modules/ngx_http_lua_module.so;
pcre_jit on;
We use Openresty, a platform that integrates nginx and Lua.
In the default nginx file, you could call Lua like so:
server {
listen 80;
listen 443 ssl; # 'ssl' parameter tells NGINX to decrypt the traffic
# 1
location ~ /api/(.*) {
resolver xxx.x.x.xx;
rewrite_by_lua_block {
ngx.req.set_header("x-header", "12345678901234567")
}
}
The alpine image here: https://github.com/openresty/docker-openresty/tree/master/
There is also an alpine-fat that had make, git and other libraries that can help you build within your Docker image.
See: "Adding third-party modules to nginx official image"
At: https://github.com/nginxinc/docker-nginx/tree/master/modules
"It's possible to extend a mainline image with third-party modules either from your own instuctions following a simple filesystem layout/syntax using build_module.sh helper script, or failing back to package sources from pkg-oss."
$ docker build --build-arg ENABLED_MODULES="ndk lua" -t my-nginx-with-lua .
You look on the Docker Hub
https://hub.docker.com/
and you find an Nginx image, based on Alpine Linux, with Lua support
Some examples
https://hub.docker.com/r/ilagnev/alpine-nginx-lua/
or
https://hub.docker.com/r/firesh/nginx-lua/
Have a look at the Dockerfile for more details
I'm working on the scenario where I need to have:
1. nginx running on the host machine
2. rails app running inside docker container
My initial work included adding Dockerfile into rails app directory on host which looks like this:
ubuntu#ubuntu-xenial:~/rails_docker$ cat Dockerfile
FROM ruby:2.1-onbuild
ENV HOME /home/rails/webapp
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
WORKDIR $HOME
# Install gems
ADD Gemfile* $HOME/
RUN bundle install
# Add the app code
ADD . $HOME
EXPOSE 8080
EXPOSE 5432
Since I already have nginx on host, it is configured to look at directory where rails application exists on host machine:
ubuntu#ubuntu-xenial:~$ cat /etc/nginx/sites-available/www.testblog.io.conf
# MANAGED BY PUPPET
server {
listen *:8080;
server_name www.testblog.io;
index index.html index.htm index.php;
access_log /var/log/nginx/www.testblog.io.access.log combined;
error_log /var/log/nginx/www.testblog.io.error.log;
location / {
root /home/ubuntu/rails_docker/public;
index index.html index.htm index.php;
}
passenger_enabled on;
passenger_ruby /usr/local/rvm/wrappers/default/ruby;
}
I'm able to build docker image and my next idea is following:
1. Declare /home/ubuntu/rails_docker as a host volume when running "rails container"
2. Expose ports 8080:8080 and 5432:5432
Command I use is following:
ubuntu#ubuntu-xenial:~/rails_docker$ docker run -d -p 8080:8080 --name examplerails -v /home/ubuntu/rails_docker:/home/rails/webapp railsapptest
82c8aa45b8c1a405e198a565feabf105d1afcbb1c37f8b7b11bf764395ed8c4e
When I check logs:
ubuntu#ubuntu-xenial:~/rails_docker$ docker logs -f examplerails
Switch to inspect mode.
For some reason, it goes into irb mode. Any idea what I'm doing wrong?
Thanks in advance,
Bakir
You need to have a CMD instruction in your Dockerfile. That is the command that is run when you start up your Docker container. If you don't specify a command, it will run whatever your FROM image uses, which you can see is 'irb' if you look at the Ruby docker image.
You can read more about the CMD instruction and everything else about Dockerfiles in the Docker documentation.