I am deploying my Next.js / Nginx docker image from Container Registry to Compute Engine
Once deployed the application is running as expected, but its running on port 3000 instead of 80 - i.e. I want to access it at <ip_address> but I can only access it on <ip_address>:3000. I have setup a reverse proxy in Nginx to forward port 3000 to 80 but it does not seem to be working.
When I run docker-compose up the app is accessible on localhost (rather than localhost:3000)
Dockerfile
FROM node:alpine as react-build
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY package.json /usr/src/app
RUN npm install
RUN npm install --global pm2
COPY . /usr/src/app
RUN npm run build
# EXPOSE 3000
EXPOSE 80
CMD [ "pm2-runtime", "start", "npm", "--", "start" ]
docker-compose.yml
version: '3'
services:
nextjs:
build: ./
nginx:
build: ./nginx
ports:
- 80:80
./nginx/Dockerfile
FROM nginx:alpine
# Remove any existing config files
RUN rm /etc/nginx/conf.d/*
# Copy config files
# *.conf files in "conf.d/" dir get included in main config
COPY ./default.conf /etc/nginx/conf.d/
./nginx/default.conf
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=STATIC:10m inactive=7d use_temp_path=off;
server {
listen 80;
gzip on;
gzip_proxied any;
gzip_comp_level 4;
gzip_types text/css application/javascript image/svg+xml;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
# BUILT ASSETS (E.G. JS BUNDLES)
# Browser cache - max cache headers from Next.js as build id in url
# Server cache - valid forever (cleared after cache "inactive" period)
location /_next/static {
#proxy_cache STATIC;
proxy_pass http://localhost:3000;
}
# STATIC ASSETS (E.G. IMAGES)
# Browser cache - "no-cache" headers from Next.js as no build id in url
# Server cache - refresh regularly in case of changes
location /static {
#proxy_cache STATIC;
proxy_ignore_headers Cache-Control;
proxy_cache_valid 60m;
proxy_pass http://locahost:3000;
}
# DYNAMIC ASSETS - NO CACHE
location / {
proxy_pass http://locahost:3000;
}
}
Related
I would like to proxy_pass to the related service conditionally based on environment variable.. What I mean, prox_pass adress should be change based on NODE_ENV variable..
What is the best approach of doing this ? Can I use if statement like as below for proxy_pass? If yes how should I do this ? Apart from this, I tried to create a bash as below as below to pass environment variable to nginx but could not able to set and pass $NGINX_BACKEND_ADDRESS to nginx conf somehow. Any help will be appreciated
if ($NODE_ENV == "development) {
proxy_pass http://myservice-dev;
}
nginx.conf
server {
listen 3000;
location / {
root /usr/src/app;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
location /csrf/token {
proxy_pass ${NGINX_BACKEND_ADDRESS}/csrf/token;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /export/apis {
proxy_pass ${NGINX_BACKEND_ADDRESS}/export/apis;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
entrypoint.sh
#!/usr/bin/env sh
set -eu
export NODE_ENV=development
if ["$NODE_ENV" == "development"]
then
export NGINX_BACKEND_ADDRESS=http://backend-dev
elif ["$NODE_ENV" == "stage"]
then
export NGINX_BACKEND_ADDRESS=http://backend-stage
elif ["$NODE_ENV" == "development"
then
export NGINX_BACKEND_ADDRESS=http://backend-preprod
elif ["$NODE_ENV" == "development"]
then
export NGINX_BACKEND_ADDRESS=http://backend
else
echo "Error in reading environment variable in nginx-conf.sh."
fi
echo "Will proxy requests for to ${NGINX_BACKEND_ADDRESS}*"
exec /nginx-conf.sh "$#"
Dockerfile
FROM nginx:alpine AS production-build
WORKDIR /usr/src/app
ARG NODE_ENVIRONMENT=development
ENV NODE_ENV=$NODE_ENVIRONMENT
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx/nginx.conf.template /etc/nginx/conf.d/default.conf.template
COPY nginx-conf.sh /
RUN chgrp -R root /var/cache/nginx /var/run /var/log/nginx /var/run/nginx.pid && \
chmod -R 775 /var/cache/nginx /var/run /var/log/nginx /var/run/nginx.pid
USER nginx
COPY --from=builder /usr/src/app/dist .
ENTRYPOINT ["/nginx-conf.sh", $NODE_ENVIRONMENT]
EXPOSE 3000
CMD ["nginx", "-g", "daemon off;"]
The Docker Hub nginx image (as of nginx:1.19) has a facility to do environment-variable replacement in configuration files:
[...] this image has a function, which will extract environment variables before nginx starts. [...] this function reads template files in /etc/nginx/templates/*.template and outputs the result of executing envsubst to /etc/nginx/conf.d.
So your first step is to rename your configuration file as is (including proxy_pass ${NGINX_BACKEND_ADDRESS}/...) to something like default.conf.template and put it in the required directory.
I would directly pass that address in your deploy-time configuration. I would not include it in the image in any way. (Imagine setups like "a developer is trying to run this stack on their local desktop system" where none of the URLs in the entrypoint script are right.) That also lets you get rid of pretty much all the code here; you would just have
# Dockerfile
FROM ... AS builder
...
FROM nginx:1.21-alpine
COPY nginx/nginx.conf.template /etc/nginx/conf.d/default.conf.template
COPY --from=builder /usr/src/app/dist /usr/share/nginx/html
# Permissions, filesystem layout, _etc._ are fine in the base image
# Use the base image's ENTRYPOINT/CMD
# docker-compose.yml
version: '3.8'
services:
proxy:
build: .
ports: ['8000:80']
environment:
- NGINX_BACKEND_ADDRESS=https://backend-prod.example.com
If you are in fact using Compose, you can use multiple docker-compose.yml files to provide settings for specific environments.
# docker-compose.local.yml
# Run the backend service locally too in development mode
version: '3.8'
services:
backend: # not in docker-compose.yml
build: backend
# and other settings as required
nginx: # overrides docker-compose.yml settings
environment:
- NGINX_BACKEND_ADDRESS=http://backend
# no other settings
docker-compose -f docker-compose.yml -f docker-compose.local.yml up
if you want to run an if statement in your dockerfile, then you can use the RUN command in the dockerfile, for example using bash,
RUN if [[ -z "$arg" ]] ; then echo Argument not provided ; else echo Argument is $arg ; fi
The way i normally do this is I have a generic nginx proxy and i then just pass in the url and protocol as env vars
ubuntu#vps-f116ed9f:/opt/docker_projects/docker_examples/load_balancer$ cat proxy.conf
server {
listen 80 default_server;
resolver 127.0.0.11 valid=1s;
set $protocol $PROXY_PROTOCOL;
set $upstream $PROXY_UPSTREAM;
location / {
proxy_pass $protocol://$upstream$request_uri;
proxy_pass_header Authorization;
proxy_http_version 1.1;
proxy_ssl_server_name on;
proxy_set_header Host $upstream;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Connection "";
proxy_buffering off;
proxy_read_timeout 5s;
proxy_redirect off;
proxy_ssl_verify off;
client_max_body_size 0;
}
}
ubuntu#vps-f116ed9f:/opt/docker_projects/docker_examples/load_balancer$ cat Dockerfile
FROM nginx:1.13.8
ENV PROXY_PROTOCOL=http PROXY_UPSTREAM=example.com
COPY proxy.conf /etc/nginx/conf.d/default.template
COPY start.sh /
CMD ["/start.sh"]
I then have a start script that will substitue the env vars into my proxy_config.
ubuntu#vps-f116ed9f:/opt/docker_projects/docker_examples/load_balancer$ cat start.sh
#!/usr/bin/env bash
envsubst '$PROXY_PROTOCOL,$PROXY_UPSTREAM' < /etc/nginx/conf.d/default.template > /etc/nginx/conf.d/default.conf
exec nginx -g 'daemon off;'
As I deploy my first ever rails app to server, I keep getting this error right when from home url.
The page you were looking for doesn't exist. You may have mistyped the address or the page may have moved.
My configuration:
Dockerfile
FROM ruby:3.0.0-alpine3.13
RUN apk add --no-cache --no-cache --update alpine-sdk nodejs postgresql-dev yarn tzdata
WORKDIR /app
COPY Gemfile .
COPY Gemfile.lock .
RUN bundle install
COPY . .
# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 4000
# Start the main process.
CMD ["rails", "server", "-b", "0.0.0.0", "-e", "production", "-p", "4000"]
entrypoint.sh
#!/bin/sh
set -e
# Remove a potentially pre-existing server.pid for Rails.
rm -f /app/tmp/pids/server.pid
# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$#"
docker-compose.yml
central:
build:
context: ./central
dockerfile: Dockerfile
command: sh -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 4000 -e production -b '0.0.0.0'"
volumes:
- ./central:/usr/src/app
env_file:
- ./central/.env.prod
stdin_open: true
tty: true
depends_on:
- centraldb
centraldb:
image: postgres:12.0-alpine
volumes:
- centraldb:/var/lib/postgresql/data/
env_file:
- ./central/.env.prod.db
nginx:
image: nginx:1.19.0-alpine
volumes:
- ./nginx/prod/certbot/www:/var/www/certbot
- ./central/public/:/home/apps/central/public/:ro
ports:
- 80:80
- 443:443
depends_on:
- central
links:
- central
restart: unless-stopped
command: '/bin/sh -c ''while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g "daemon off;"'''
nginx.conf
upstream theapp {
server central:4000;
}
server {
listen 80;
server_name thedomain.com;
server_tokens off;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name thedomain.com;
if ($scheme = http) {
return 301 https://$server_name$request_uri;
}
# hidden ssl config
root /home/apps/central/public;
index index.html;
location ~ ^/(assets|images|javascripts|stylesheets|swfs|system)/ {
try_files $uri #rails;
access_log off;
gzip_static on;
# to serve pre-gzipped version
expires max;
add_header Cache-Control public;
add_header Last-Modified "";
add_header ETag "";
break;
}
location ~ /\. {
deny all;
}
location ~* ^.+\.(rb|log)$ {
deny all;
}
location / {
try_files $uri #rails;
}
location #rails {
proxy_pass http://theapp;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_redirect off;
client_max_body_size 4G;
keepalive_timeout 10;
}
# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /home/apps/central/public;
}
error_log /var/log/nginx/central_error.log;
access_log /var/log/nginx/central_access.log;
}
As I check the log file of nginx but it doesn't show anything.
The app work well in my local and even in production with ports config (of course if I go to thedomain.com:4000), but I need to serve it with Nginx in production with thedomain.com so I need solution for this.
I found it very strange, I had setup an rails app, posgres db, and a nginx server for production only but the ngix only able to start if I type
docker-compose -f docker-compose.yml -f production.yml up --build
but not the pre-build
docker-compose -f docker-compose.yml -f production.yml build
then
docker-compose up
the rails app and db is starting just fine is just that nginx is not started and the port is revert back to port 3000 instead of 80 which i found very strange isn't they doing the same thing?
nginx.conf
# This is a template. Referenced variables (e.g. $INSTALL_PATH) need
# to be rewritten with real values in order for this file to work.
upstream rails_app {
server unix:///webapp/tmp/sockets/puma.sock;
}
server {
listen 80;
# define your domain
server_name 127.0.0.1 localhost www.example.com;
# define the public application root
root /providre_api/public;
# define where Nginx should write its logs
access_log /providre_api/log/nginx.access.log;
error_log /providre_api/log/nginx.error.log;
# deny requests for files that should never be accessed
location ~ /\. {
deny all;
}
location ~* ^.+\.(rb|log)$ {\
deny all;
}
# serve static (compiled) assets directly if they exist (for rails production)
location ~ ^/(assets|images|javascripts|stylesheets|swfs|system)/ {
try_files $uri #rails;
access_log off;
gzip_static on; # to serve pre-gzipped version
expires max;
add_header Cache-Control public;
# Some browsers still send conditional-GET requests if there's a
# Last-Modified header or an ETag header even if they haven't
# reached the expiry date sent in the Expires header.
add_header Last-Modified "";
add_header ETag "";
break;
}
# send non-static file requests to the app server
location / {
try_files $uri #rails;
}
location #rails {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://rails_app;
}
}
web.Dockerfile
# Base image:
FROM nginx
# Install dependencies
RUN apt-get update -qq && apt-get -y install apache2-utils
# establish where Nginx should look for files
ENV INSTALL_PATH /providre_api
# Set our working directory inside the image
WORKDIR $INSTALL_PATH
# create log directory
RUN mkdir log
# copy over static assets
COPY public public/
# Copy Nginx config template
COPY docker/web/nginx.conf /tmp/docker.nginx
# substitute variable references in the Nginx config template for real values from the environment
# put the final config in its place
RUN envsubst '$INSTALL_PATH' < /tmp/docker.nginx > /etc/nginx/conf.d/default.conf
EXPOSE 80
# Use the "exec" form of CMD so Nginx shuts down gracefully on SIGTERM (i.e. `docker stop`)
CMD [ "nginx", "-g", "daemon off;" ]
docker-compose.yml
version: '3'
services:
db:
image: postgres
volumes:
- ./tmp/db:/var/lib/postgresql/data
restart: always
ports:
- "5433:5432"
environment:
POSTGRES_USER: 'postgres'
POSTGRES_PASSWORD: ''
app:
command: bundle exec puma -C config/puma.rb
ports:
- "3000"
depends_on:
- db
docker-compose.override.yml
version: '3'
services:
app:
build:
context: .
dockerfile: ./docker/app/Dockerfile
volumes:
- .:/providre_api
ports:
- "3000:3000"
production.yml
version: '3'
services:
app:
build:
context: .
dockerfile: ./docker/app/prod.Dockerfile
volumes:
- .:/providre_api
ports:
- "3000"
nginx:
container_name: web
build:
context: .
dockerfile: ./docker/web/web.Dockerfile
depends_on:
- app
volumes:
- ./docker/web/nginx.conf:/etc/nginx/conf.d/default.conf
ports:
- 80:80
Sorry my bad I didn't test it fully so the docker-compose up will used the normal docker-compose.yml so I have to repeat and use docker-compose -f docker-compose.yml -f production.yml up instead
I'm trying to setup a docker environment using docker-compose with images of
rails (running puma), nginx, mysql, elasticsearch.
But when I try to call it using HTTParty.get('http://lvh.me:8888')
it's fail and I got an error message
Errno::ECONNREFUSED (Failed to open TCP connection to lvh.me:8888
(Connection refused - connect(2) for "lvh.me" port 8888))
My Docker-Compose file:
version: '3.3'
services:
beecomredis:
image: redis:4.0.8
ports:
- "6379:6379"
beecomdb:
image: mysql:5.7.21
volumes:
- ./mysql_data/mysql:/var/lib/mysql
ports:
- "6603:3306"
beecomec:
image: docker.elastic.co/elasticsearch/elasticsearch:6.2.2
#container_name: elasticsearch
environment:
- http.cors.enabled=true
- http.cors.allow-origin="*"
- node.master=true
- cluster.name=docker-cluster
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
- xpack.security.enabled=false
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- ./elastic_data/elasticsearch/data:/usr/share/elasticsearch/data
- ./elastic_data/elasticsearch/logs:/usr/share/elasticsearch/logs
ports:
- '9200:9200'
- '9300:9300'
beecomnginx:
build:
context: .
dockerfile: Dockerfile-nginx
ports:
- "8888:80"
beecom:
build: .
command: foreman start
volumes:
- .:/beecom
expose:
- "3000"
depends_on:
- beecomdb
- beecomredis
- beecomec
- beecomnginx
My nginx.conf file:
upstream rails_app {
server beecom:3000;
}
server {
# define your domain
server_name www.example.com;
# define the public application root
root $RAILS_ROOT/public;
index index.html;
# define where Nginx should write its logs
access_log $RAILS_ROOT/log/nginx.access.log;
error_log $RAILS_ROOT/log/nginx.error.log;
# deny requests for files that should never be accessed
location ~ /\. {
deny all;
}
location ~* ^.+\.(rb|log)$ {
deny all;
}
# serve static (compiled) assets directly if they exist (for rails production)
location ~ ^/(assets|images|javascripts|stylesheets|swfs|system)/ {
try_files $uri #rails;
access_log off;
gzip_static on;
# to serve pre-gzipped version
expires max;
add_header Cache-Control public;
add_header Last-Modified "";
add_header ETag "";
break;
}
# send non-static file requests to the app server
location / {
try_files $uri #rails;
}
location #rails {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://rails_app;
}
}
My DockerFile:
FROM ruby:2.5.0-slim
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
default-libmysqlclient-dev \
mysql-client \
libmagickwand-dev \
imagemagick \
curl \
git \
gnupg2 \
/sources.list.d/yarn.list \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
RUN curl -sL https://deb.nodesource.com/setup_9.x | bash - && apt-get install -y --no-install-recommends nodejs
RUN gem update --system
RUN mkdir -p /beecom
WORKDIR /beecom
COPY Gemfile Gemfile
COPY Gemfile.lock Gemfile.lock
COPY package.json package.json
ENV RAILS_ENV development
ENV RACK_ENV development
RUN bundle install
RUN set :environment, 'development'
COPY config/puma.rb config/puma.rb
COPY . /beecom
EXPOSE 3000
CMD [ "foreman", "start" ]
And finally my Dockerfile-nginx :
# Base image:
FROM nginx
# Install dependencies
RUN apt-get update -qq && apt-get -y install apache2-utils
# establish where Nginx should look for files
ENV RAILS_ROOT /beecom
# Set our working directory inside the image
RUN mkdir -p $RAILS_ROOT
WORKDIR $RAILS_ROOT
# create log directory
RUN mkdir log
# copy over static assets
COPY ./public public/
# Copy Nginx config template
COPY ./config/nginx.conf /tmp/docker.nginx
# substitute variable references in the Nginx config template for real values from the environment
# put the final config in its place
RUN envsubst '$RAILS_ROOT' < /tmp/docker.nginx > /etc/nginx/conf.d/default.conf
RUN rm -rf /etc/nginx/sites-available/default
ADD config/nginx.conf /etc/nginx/sites-enabled/nginx.conf
EXPOSE 80
# Use the "exec" form of CMD so Nginx shuts down gracefully on SIGTERM (i.e. `docker stop`)
CMD [ "nginx", "-g", "daemon off;" ]
Oh and I forgot to post my Puma config:
# Puma can serve each request in a thread from an internal thread pool.
# The `threads` method setting takes two numbers a minimum and maximum.
# Any libraries that use thread pools should be configured to match
# the maximum value specified for Puma. Default is set to 5 threads for minimum
# and maximum, this matches the default thread size of Active Record.
#
threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }.to_i
threads threads_count, threads_count
# Specifies the `port` that Puma will listen on to receive requests, default is 3000.
#
port ENV.fetch("PORT") { 3000 }
# Specifies the `environment` that Puma will run in.
#
environment ENV.fetch("RAILS_ENV") { "development" }
# Specifies the number of `workers` to boot in clustered mode.
# Workers are forked webserver processes. If using threads and workers together
# the concurrency of the application would be max `threads` * `workers`.
# Workers do not work on JRuby or Windows (both of which do not support
# processes).
#
workers ENV.fetch("WEB_CONCURRENCY") { 3 }
# Use the `preload_app!` method when specifying a `workers` number.
# This directive tells Puma to first boot the application and load code
# before forking the application. This takes advantage of Copy On Write
# process behavior so workers use less memory. If you use this option
# you need to make sure to reconnect any threads in the `on_worker_boot`
# block.
#
# preload_app!
# The code in the `on_worker_boot` will be called if you are using
# clustered mode by specifying a number of `workers`. After each worker
# process is booted this block will be run, if you are using `preload_app!`
# option you will want to use this block to reconnect to any threads
# or connections that may have been created at application boot, Ruby
# cannot share connections between processes.
#
# on_worker_boot do
# ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
# end
# Allow puma to be restarted by `rails restart` command.
plugin :tmp_restart
Finally I found that adding a binding to my config/puma.rb file.
bind 'tcp://0.0.0.0:8888'
Resolved my problem.
UPDATED:
Finally the best way I found to fix this was to change my nginx.config like so:
upstream MyAppUpstream_website {
server website:3000;
}
server {
listen 443 ssl;
listen 80;
server_name lvh.me
keepalive_timeout 900;
ssl_certificate /[key];
ssl_certificate_key /[key];
# define the public application root
root $RAILS_ROOT/public;
index index.html;
# define where Nginx should write its logs
access_log $RAILS_ROOT/log/nginx.access.log;
error_log $RAILS_ROOT/log/nginx.error.log;
# deny requests for files that should never be accessed
location ~ /\. {
deny all;
}
location ~* ^.+\.(rb|log)$ {
deny all;
}
# serve static (compiled) assets directly if they exist (for rails production)
location ~ ^/(assets|images|javascripts|stylesheets|swfs|system)/ {
try_files $uri #rails;
access_log off;
gzip_static on;
# to serve pre-gzipped version
expires max;
add_header Cache-Control public;
add_header Last-Modified "";
add_header ETag "";
break;
}
# send non-static file requests to the app server
location / {
try_files $uri #rails;
}
location #rails {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://MyAppUpstream_website;
}
}
I'm very new to Docker and Nginx and this might be a stupid question but how can I point my nginx box to look at the files in Rails public? Basically, I have an nginx box, and an application box. I would like to know where I can put those files so that the nginx box can read them.
version: "3"
services:
api:
build: "./api"
env_file:
- .env-dev
ports:
- "3000:3000"
depends_on:
- db
volumes:
- .:/app/api
command: rails server -b "0.0.0.0"
nginx:
build: ./nginx
env_file: .env-dev
volumes:
- .:/app/nginx
depends_on:
- api
links:
- api
ports:
- "80:80"
...
Api dockerfile:
FROM ruby:2.4.1-slim
RUN apt-get update && apt-get install -qq -y \
build-essential \
libmysqlclient-dev \
nodejs \
--fix-missing \
--no-install-recommends
ENV INSTALL_PATH /api
RUN mkdir -p $INSTALL_PATH
WORKDIR $INSTALL_PATH
COPY Gemfile $INSTALL_PATH
RUN bundle install
COPY . .
EXPOSE 3000
Nginx Dockerfile:
FROM nginx
ENV INSTALL_PATH /nginx
RUN mkdir -p $INSTALL_PATH
COPY nginx.conf /etc/nginx/nginx.conf
# COPY ?
EXPOSE 80
nginx config (this is correctly being copied over)
daemon off;
worker_processes: 1;
events { worker_connections: 1024; }
http {
sendfile on;
gzip on;
gzip_http_version 1.0;
gzip_proxied any;
gzip_min_length 500;
gzip_disable "MSIE [1-6]\.";
gzip_types text/plain text/xml text/css
text/comma-separated-values
text/javascript
application/x-javascript
application/atom+xml;
# Rails Api
upstream api {
server http://api/;
}
# Configuration for the server
server {
# Running port
listen 80;
# Proxying the connections connections
location /api {
proxy_pass http://api;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
error_page 500 502 503 504 /public/50x.html
error_page 404 /public/404.html
location = /50x.html {
root /api/public;
}
location = /404.html {
root /api/public
}
}
}
Now, when I go to localhost:80 it show the generic nginx folder. However, I'm unsure how to link the public dir of rails api/public/ to the nginx container.
Can I just COPY path/to/rails/public path/nginx. Where is nginx expecting to find those files?
Edit
I believe I should be putting them in /var/www/app_name, correct?
I think what you want to achieve should be done by mounting a volume of container 'api' to container 'nginx', something like this:
version: "3"
services:
api:
image: apiimg
volumes:
- apivol:/path/to/statics
nginx:
image: nginximg
volumes:
- apivol:/var/www/statics
volumes:
apivol: {}
So there's a shared volume declared for all containers, apivol, which is mapped to /path/to/statics on your Rails container, and to /var/www/statics in your nginx container. This way you don't need to copy anything manually into the nginx container.
The default location for static content on nginx is /etc/nginx/html, but you could put it in var/www/app_name as long as you remember to add
root /var/www/app_name
in the corresponding location block for your static content.