skip to Main Content

I am trying to setup ruby on rails with docker everything is good but i want dynamic domain pass as environment variable to nginx.conf file during build image by docker-compose command but i don’t know how to do it.
i trying to use this command
Docker-compose build
dcoker-compose up

Docker File

FROM ruby:2.7.2
ENV RAILS_ROOT /var/www/quickcard
ENV BUNDLE_VERSION 2.1.4
ENV BUNDLE_PATH usr/local/bundle/gems
ENV RAILS_LOG_TO_STDOUT true
ENV RAILS_PORT 5000
COPY ./entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
RUN apt-get update -qq && apt-get install -y build-essential 
git 
libxml2-dev 
libpq-dev 
libxslt-dev 
nodejs 
yarn 
imagemagick 
tzdata 
less 
cron 
&& rm -rf /var/cache/apk/*
RUN gem install bundler --version "$BUNDLE_VERSION"
RUN mkdir -p $RAILS_ROOT
WORKDIR $RAILS_ROOT
ADD Gemfile Gemfile
ADD Gemfile.lock Gemfile.lock
COPY yarn.lock yarn.lock
RUN bundle install
EXPOSE $RAILS_PORT
RUN ln -s $RAILS_ROOT/config/systemd/puma.service /etc/systemd/system/quickcard
COPY . .
RUN crontab -l | { cat; echo ""; } | crontab -
RUN yarn install
RUN yarn install --check-files
RUN ls /var/www/quickcard/public
ENTRYPOINT ["entrypoint.sh"]
CMD ["bundle", "exec", "puma", "-C", "config/puma.rb"]

Nginx Docker File

FROM nginx
RUN apt-get update -qq && apt-get -y install apache2-utils
ENV RAILS_ROOT /var/www/quickcard
WORKDIR $RAILS_ROOT
RUN mkdir log
COPY public public/

COPY ./nginx.conf /etc/nginx/conf.d/default.conf
COPY ./multi_quickcard.key /etc/nginx/multi_quickcard.key
COPY ./quickcard-ssl-test.pem /etc/nginx/quickcard-ssl-test.pem

EXPOSE 80 443
CMD [ "nginx", "-g", "daemon off;" ]

Nginx.conf e.g

upstream puma {
    # Path to Puma SOCK file, as defined previously
    server app:5000 fail_timeout=0;
}

server {
    listen 80;
    server_name default_server;

    index index.html index.htm;
    try_files $uri $uri/ /index.html =404;

    location / {
        root /var/www/quickcard/public/;
        proxy_pass http://puma;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
    }

    location /api {
        root /var/www/quickcard/public/;
        proxy_pass http://puma;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
    }

    location ^~ /assets/ {
        root /var/www/quickcard/public/;
        gzip_static on;
        expires max;
        add_header Cache-Control public;
    }

    error_page 500 502 503 504 /500.html;
    client_max_body_size 4G;
    keepalive_timeout 10;
}

Docker Compose File

version: '2.2'
services:
  app:
    build: 
      context: .
      dockerfile: ./Dockerfile
    command: bash -c "bundle exec rails s -p 5000 -e production -b 0.0.0.0 &&  RAILS_ENV=production bundle exec rake assets:precompile"
    environment:
      RAILS_ENV: production
    volumes:
      - /var/wwww/quickcard
      - /var/wwww/quickcard/public
    ports:
      - 5000:5000
  sidekiq:
    build: .
    command: bundle exec sidekiq -C config/sidekiq.yml
    environment:
      RAILS_ENV: production
    volumes:
      - /var/wwww/quickcard/tmp
  cron_job:
    build: .
    command: cron -f
  nginx:
    build:
      context: .
      dockerfile: ./nginx.Dockerfile
    volumes:
      - ./log-nginx:/var/log/nginx/
    restart: always
    ports:
      - 80:80
      - 443:443

2

Answers


  1. The recommended approach Nginx seems to be to use the envsubst utility. You would need to create a template file with the variable placed inside as $Variable or {Variable}. You could then pass into envsubst the template file which would render the variable from the environment.

    This has a few downsides in that it can potentially replace nginx variables unintentionally so I would make sure to pass in the specific variables you would want to replace.

    See this question which addresses a similar problem for more details: https://serverfault.com/questions/577370/how-can-i-use-environment-variables-in-nginx-conf

    Login or Signup to reply.
  2. nginx Docker image can extract environment variables before it starts, but it’s a bit tricky. One solution is to:

    1. Add env variables to your nginx.conf file.
    2. Copy it to /etc/nginx/templates/nginx.conf.template in the container (as opposed to your normal /etc/nginx) in the build step or as a volume.
    3. Set the NGINX_ENVSUBST_OUTPUT_DIR: /etc/nginx environment variable in docker-compose.yml.

    This will cause the nginx.conf.template file to be copied to /etc/nginx as nginx.conf and the environment variables will be replaced with their values.

    There is one caveat to keep in mind: using command property in docker-compose.yml seems to be disabling the extraction functionality. If you need to run a custom command to start-up nginx, you can use the Dockerfile version.

    I created a repo with the full setup, but in case it’s not available:

    # docker-compose.yml
    
    version: "3"
    services:
      nginx-no-dockerfile:
        container_name: nginx-no-dockerfile
        image: nginx:1.23.1-alpine
        ports:
          - 8081:80
        volumes:
          - ./site/index.html:/usr/share/nginx/html/index.html
          - ./site/nginx.conf:/etc/nginx/templates/nginx.conf.template
        working_dir: /usr/share/nginx/html
        environment:
          NGINX_ENVSUBST_OUTPUT_DIR: /etc/nginx
          API_URL: http://example.com
    
    
      nginx-with-dockerfile:
        container_name: nginx-with-dockerfile
        build:
          context: ./site
          dockerfile: ./Dockerfile
        ports:
          - 8082:80
        volumes:
          - ./site/index.html:/usr/share/nginx/html/index.html
        environment:
          NGINX_ENVSUBST_OUTPUT_DIR: /etc/nginx
          API_URL: http://example.com
    
    # site/nginx.conf
    
    worker_processes auto;
    
    events {
    }
    
    http {
      include /etc/nginx/mime.types;
    
      server {
        listen 80;
    
        root /usr/share/nginx/html;
        index index.html index.htm;
    
        location / {
          try_files $uri $uri/ /index.html;
        }
    
        location /example {
          proxy_pass $API_URL;
        }
      }
    }
    
    # site/Dockerfile
    
    FROM nginx:1.23.1-alpine
    
    WORKDIR /usr/share/nginx/html
    COPY ./nginx.conf /etc/nginx/templates/nginx.conf.template
    
    EXPOSE 80
    CMD ["nginx", "-g", "daemon off;"]
    

    Run no Dockerfile version: docker compose up nginx-no-dockerfile

    Run Dockerfile version:

    docker compose build nginx-with-dockerfile
    docker compose up nginx-with-dockerfile
    
    

    Make sure to also have index.html file in the site folder.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search