Custom Nginx conf not reflecting in uwsgi-nginx docker image - docker

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.

Related

Docker container has not set GOPATH correctly

I have a problem when I try to run my app in a Docker container. It is running fine with a simple go run main.go, but whenever I build an image and I run the docker container, I got the error of panic: html/template: pattern matches no files: *.html, so I guess GOPATH is not properly set in the docker container (tho I use this same docker file from other projects and I don't have any problems). I am a little lost here, since this method I been using already for a while without problems.
I am using gin as a framework for develop.
The docker file is:
FROM golang:alpine as builder
RUN apk update && apk add git && apk add ca-certificates
# For email certificate
RUN apk add -U --no-cache ca-certificates
COPY . $GOPATH/src/github.com/kiketordera/advanced-performance/
WORKDIR $GOPATH/src/github.com/kiketordera/advanced-performance/
RUN go get -d -v $GOPATH/src/github.com/kiketordera/advanced-performance
# For Cloud Server
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags="-w -s" -o /go/bin/advanced-performance $GOPATH/src/github.com/kiketordera/advanced-performance
FROM scratch
COPY --from=builder /go/bin/advanced-performance /advanced-performance
COPY --from=builder /go/src/github.com/kiketordera/advanced-performance/media/ /go/src/github.com/kiketordera/advanced-performance/media/
# For email certificate
VOLUME /etc/ssl/certs/ca-certificates.crt:/etc/ssl/certs/ca-certificates.crt
COPY --from=alpine /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
EXPOSE 8050/tcp
ENV GOPATH /go
ENTRYPOINT ["/advanced-performance"]
Main function is:
package main
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
i18n "github.com/suisrc/gin-i18n"
"golang.org/x/text/language"
)
func main() {
// We create the instance for Gin
r := gin.Default()
/* Internationalization for showing the right language to match the browser's default settings
*/
bundle := i18n.NewBundle(
language.English,
"text/en.toml",
"text/es.toml",
)
// Tell Gin to use our middleware. This means that in every single request (GET, POST...), the call to i18n will be executed
r.Use(i18n.Serve(bundle))
// Path to the static files. /static is rendered in the HTML and /media is the link to the path to the images, svg, css.. the static files
r.StaticFS("/static", http.Dir("media"))
// Path to the HTML templates. * is a wildcard
r.LoadHTMLGlob("*.html")
// Redirects when users introduces a wrong URL
r.NoRoute(redirect)
// This get executed when the users gets into our website in the home domain ("/")
r.GET("/", renderHome)
r.POST("/", getForm)
// Listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
r.Run()
}
The full project can be found in https://github.com/kiketordera/advanced-performance, is a simple website rendering with i18n and a POST form-handler
GOPATH is not relevant; it's used to "resolve import statements" and plays no role when running an executable (unless your code references it specifically!). The WORKDIR is the issue here.
FROM "clears any state created by previous instructions". This includes the WORKDIR. For example if you use the docker file:
FROM alpine:3.12
WORKDIR /test
copy 1.txt .
FROM alpine:3.12
copy 2.txt .
The final resulting image will have file 2.txt in the root folder (and no /test folder).
In your dockerfile you are copying the media folder to /go/src/github.com/kiketordera/advanced-performance/media/ on the assumption that the WORKDIR will be set; but that is not the case (it defaults to /). Simplest fix is to change COPY --from=builder /go/src/github.com/kiketordera/advanced-performance/media/ /go/src/github.com/kiketordera/advanced-performance/media/ to COPY --from=builder /go/src/github.com/kiketordera/advanced-performance/media/ /media/.
You are also accessing files from the root folder so need to copy these in with COPY --from=builder /go/src/github.com/kiketordera/advanced-performance/*.html / (or similar). Given that you are doing this it's probably best to put everything (the exe, html files and media folder) into a folder (e.g. /app) to keep the root folder clean.
Note: There is no need to set GOPATH in the second image; as mentioned above it's not relevant when running the executable. I'd recommend using modules (support for GOPATH will probably be dropped in 1.17); this would also enable you to considerably shorten your paths!

Docker COPY on multistage build doens't working

I'm using multistage build to compile an react app.
Primarily I use a base node image, after I use a nginx image to expose to the port 80.
I'm attempting to COPY the build files from builder stage to the /usr/share/nginx/html folder, but gets nothing.
Building the image alone it's working, with docker-compose does nothing.
I attempted to open an issue on the docker repo but is closed, therefore open on the moby engine also is not a option when the podman(that's use moby engine) works well, except the compose that spawn a command as not sudoers and the build fail on the node image download.
FROM node:slim as build
WORKDIR /usr/app
COPY package.json .
COPY public public
COPY src src
RUN npm install
RUN npm run build
COPY build .
RUN rm -rf src
RUN rm -rf build
FROM nginx:latest
COPY --from=build /usr/app /usr/share/nginx/html
# RUN chown www-data:www-data ./usr/share/nginx/html/*
EXPOSE 80
On the ls command I see the build, but when I'm attempt to connect to localhost a get the forbidden error, and when attempt to access the index.html I'm getting the 404.
I entered on the the html folder using bash and verify using the namei -l . and there's no file at all.
What could I be doing wrong? I've searched a ton of questions and don't get the answer or any direction, execpt the fact of add a slash of the folder to be copied.
Currently I'm using a RHEL. So, needs sudoers permission to run docker commands. Maybe it's the problem? On podman-compose I need to spawn an sudo docker-compose build command, and it run another build commands as non root.
Therefore, this not occurs on docker-ce.
First of all, ensure you have a correct nginx config in the file nginx.conf. e.g:
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
Second, it's not necessary run these lines:
COPY build . # you should call directly the build folder, because there isn't any other files of build stage
RUN rm -rf src #after finish build step, this image will no longer exist.
RUN rm -rf build
RUN ls
Finally your Dockerfile should look like this
FROM node:slim as build
WORKDIR /usr/app
COPY package.json .
COPY public public
COPY src src
RUN npm install
RUN npm run build
FROM nginx:latest
COPY --from=build /usr/app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d
# if you are using react router
# you need to overwrite the default nginx configurations
# remove default nginx configuration file
RUN rm /etc/nginx/conf.d/default.conf
EXPOSE 80

Dockerfile FROM AS throws Invalid Reference Format

I'm trying to use a multistep Dockerfile that uses FROM AS, but when I run the Dockerfile in a Jenkins job I get an error
FROM node:8.12.0-alpine AS firstStep
Error parsing reference: "node:8.12.0-alpine AS firstStep" is not a valid repository/tag: invalid reference format
The Dockerfile is this:
FROM node:8.12.0-alpine AS firstStep
WORKDIR /usr/src/app/
# Copy both the package.json and the package-lock.json
COPY package*.json ./
COPY . .
# Deployment container
FROM nginx:1.14.0-alpine
RUN apk add --no-cache bash
RUN apk add --update curl
#set env var for certs
ENV NODE_EXTRA_CA_CERTS /confs/MyPem.pem
# Forward logs to stdout and stderr
RUN ln -sf /dev/stdout /var/log/nginx/access.log \
&& ln -sf /dev/stderr /var/log/nginx/error.log
# Create nginx config dir and copy nginx files for environments into it
RUN mkdir /confs
COPY ./nginxconf/* /confs/
#This copies the Keystore from the workspace and places it at the root of the container
COPY ./MyPem.pem /confs/MyPem.pem
COPY --from=firstStep /usr/src/app/dist /usr/share/nginx/html
COPY ./entrypoint.sh /opt/entrypoint.sh
RUN chmod a+x /opt/entrypoint.sh
ENTRYPOINT ["/opt/entrypoint.sh"]
If you check in dockerhub.com the image node:8.12.0-alpine indeed does not exists, Use for example "node:8.12-alpine" . Also you should use lowercase for "firstStep" so ... "firststep"
Support for multi-stage builds was added in 17.05.0. You can check the current version of the docker client and server with docker version. You'll need to upgrade the docker engine performing the build. Older docker releases are not supported once a new major release is delivered, so you'll want to pick a current stable release. Follow the installation guide from docker for your platform to install from the docker repos, you'll often find that Linux distributions have older versions of docker in their repos.

Where to place nginx.conf file in docker container

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.

Automatic build with Add from URL

I'm trying to do a auto build on hub.docker.com using a ADD with files from a URL. I have the following docker file on github, builds are being triggered:
FROM ubuntu:14.04
MAINTAINER Andy Cobley "andy#example.org"
ENV REFRESHED_AT 2015-29-04
RUN apt-get update
RUN apt-get install -y nginx
RUN mkdir -p /var/www/html
ADD http://example.org:8080/global.conf /etc/nginx/conf.d/
ADD http://example.org:8080/nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
ENTRYPOINT ["/usr/sbin/nginx"]
The files are not being added into the container. I can confirm the files do exist on the server and are accessible. Is there something I'm missing ?
As your first ADD ends with a /, docker thinks the source (global.conf) is a directory, try with ADD http://example.org:8080/global.conf /etc/nginx/conf.d/global.conf
I think I've solved this. building remotely in this situation you need to do a docker pull before doing a docker run.

Resources