Nginx build failure on specific Rails On Docker config... shared volumes problem?

Hi everyone,

I’m getting started on Docker, and for a small Rails application I just achieved a specific setup to improve workflow using Gitlab CI/CD: https://gitlab.com/soykje/rails-on-docker.
The idea is to build the app docker image on release stage, and then save it on Gitlab image registry in order to deploy it using a specific Compose file. And everything seems to work just fine! :slight_smile:

And so I wanted to go further, by adding an Nginx container (first step would be to use it for SSL certificates management). In development mode, it seems to be ok, but if I try to add my container on deployment compose file, it fails build Nginx container, with the following error (on a project base on the linked one):

Service 'nginx' failed to build: COPY failed: stat /var/lib/docker/tmp/docker-builder917066868/public: no such file or directory

Please do not hesitate to have a look at my public repository! Anyway, here is a few snippets to help you understand:

.gitlab-ci.yml

image: docker
services:
  - docker:dind

cache:
  paths:
    - node_modules

variables:
  DOCKER_HOST: tcp://docker:2375/
  DOCKER_DRIVER: overlay2
  CONTAINER_LATEST_IMAGE: $CI_REGISTRY_IMAGE:latest
  CONTAINER_STABLE_IMAGE: $CI_REGISTRY_IMAGE:stable

stages:
  - test
  - release
  - deploy

before_script:
  - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
  - apk add --no-cache py-pip python-dev libffi-dev openssl-dev gcc libc-dev make
  - pip install docker-compose
  - docker-compose --version

test:
  stage: test
  script:
    - docker-compose -f docker-compose.test.yml build --pull
    - docker-compose -f docker-compose.test.yml run --rm app sh -c "./docker/wait_for_services.sh && bundle exec rake db:create spec && yarn jest"
  after_script:
    - docker-compose -f docker-compose.test.yml run --rm app rm -rf tmp/
    - docker-compose -f docker-compose.test.yml down
    - docker volume rm `docker volume ls -qf dangling=true`

release_staging:
  stage: release
  only:
    - staging
  script:
    - docker-compose -f docker-compose.staging.yml build --pull
    - docker tag beweeg_staging $CONTAINER_LATEST_IMAGE
    - docker push $CONTAINER_LATEST_IMAGE

release_production:
  stage: release
  only:
    - production
  script:
    - docker-compose -f docker-compose.production.yml build --pull
    - docker tag beweeg_production $CONTAINER_STABLE_IMAGE
    - docker push $CONTAINER_STABLE_IMAGE

deploy_staging:
  stage: deploy
  only:
    - staging
  environment: production
  before_script:
    - mkdir -p ~/.ssh
    - echo "$STAGING_SERVER_PRIVATE_KEY" | tr -d '\r' > ~/.ssh/id_rsa
    - chmod 600 ~/.ssh/id_rsa
    - which ssh-agent || (apk add openssh-client)
    - eval $(ssh-agent -s)
    - ssh-add ~/.ssh/id_rsa
    - ssh-keyscan -H $STAGING_SERVER_IP >> ~/.ssh/known_hosts
  script:
    - scp -rp ./docker-deploy.staging.yml ./nginx/nginx.conf ./nginx/Dockerfile-nginx root@${STAGING_SERVER_IP}:~/
    - ssh root@$STAGING_SERVER_IP "docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY};
      docker pull $CONTAINER_LATEST_IMAGE;
      docker-compose -f docker-deploy.staging.yml stop;
      docker-compose -f docker-deploy.staging.yml rm app --force;
      docker-compose -f docker-deploy.staging.yml up -d"

deploy_production:
  stage: deploy
  only:
    - production
  environment: production
  before_script:
    - mkdir -p ~/.ssh
    - echo "$PRODUCTION_SERVER_PRIVATE_KEY" | tr -d '\r' > ~/.ssh/id_rsa
    - chmod 600 ~/.ssh/id_rsa
    - which ssh-agent || (apk add openssh-client)
    - eval $(ssh-agent -s)
    - ssh-add ~/.ssh/id_rsa
    - ssh-keyscan -H $PRODUCTION_SERVER_IP >> ~/.ssh/known_hosts
  script:
    - scp -rp ./docker-deploy.production.yml root@${PRODUCTION_SERVER_IP}:~/
    - ssh root@$PRODUCTION_SERVER_IP "docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY};
      docker pull $CONTAINER_STABLE_IMAGE;
      docker-compose -f docker-deploy.production.yml stop;
      docker-compose -f docker-deploy.production.yml rm app --force;
      docker-compose -f docker-deploy.production.yml up -d"

docker-compose.staging.yml

version: '3.0'
services:
  app:
    image: beweeg_staging
    build:
      context: .
      args:
        - PRECOMPILEASSETS=YES
    environment:
      - RAILS_ENV=production
      - APP_HOST=staging.beweeg.fr
      - APP_PROTOCOL=http
      - [...]
    ports:
      - 3000:3000
    volumes:
      - .:/beweeg

docker-deploy.staging.yml

version: '3'
services:
  db:
    image: postgres:11-alpine
    ports:
      - 5432:5432
    environment:
      POSTGRES_PASSWORD: postgres

  app:
    image: registry.gitlab.com/soykje/beweeg-ror:latest
    environment:
      - RAILS_ENV=production
      - APP_HOST=staging.beweeg.fr
      - APP_PROTOCOL=http
      - [...]
    links:
      - db
    ports:
      - 3000:3000
    volumes:
      - .:/beweeg

  nginx:
    build:
      context: .
      dockerfile: ./Dockerfile-nginx
    environment:
      - SERVER_NAME=staging.beweeg.fr
    depends_on:
      - app
    ports:
      - 80:80
    volumes:
      - .:/beweeg

I tried several things on volumes declarations, and also tried to clean the .dockerignore file (removing public/ from it). But nothing works… I’m quite lost here, and too much a noob to understand really the origin of my issue, in order to fix it. Is it my whole logic (using Gitlab registry) that I should change, or something else in my docker-deploy.staging.yml?

Anyway, I hope that someone will be able to take some time to help me… I want to learn but I miss the basics I guess so do not hesitate to help me learning more on Docker!

Thx in advance