skip to Main Content

Context : Rails 6 app hosted in Docker, using docker-compose

When the Rails container starts, I get :
Mysql2::Error::ConnectionError: Access denied for user 'user'@'%' to database 'db_production'
Even after MySQL is fully initalized

My docker-compose.yml :

services:

  app_production:
    image: app_production
    build:
      context: .
      dockerfile: ./dockerfiles/production.dockerfile
    container_name: app_production
    volumes:
      - ./public:/app_production/public
      - mysql_socket:/var/run/mysqld
    command: bash -c "sleep 5 && bundle exec rails db:create db:migrate && bundle exec puma -C config/puma.rb"
    restart: always
    environment:
      RAILS_ENV: production
      SECRET_KEY_BASE: ${PRODUCTION_SECRET_KEY_BASE}
      APP_DATABASE_PASSWORD: ${PRODUCTION_MYSQL_PASSWORD}
      PORT: 5000
    ports:
      - "5000:5000"
    depends_on:
      - database_production
    links:
      - database_production


  database_production:
    image: mysql:8.0.20
    command: mysqld --default-authentication-plugin=mysql_native_password
    restart: always
    container_name: database_production
    environment:
      MYSQL_USER: user
      MYSQL_PASSWORD: ${PRODUCTION_MYSQL_PASSWORD}
      MYSQL_RANDOM_ROOT_PASSWORD: "yes"
    volumes:
      - dbdata_production:/var/lib/mysql
      - mysql_socket:/var/run/mysqld
    ports:
      - "3307:3306"


volumes:
 dbdata_production:
 mysql_socket:

My Dockerfile :

FROM ruby:2.6.1

RUN echo "deb http://archive.debian.org/debian stretch main" > /etc/apt/sources.list
RUN curl https://deb.nodesource.com/setup_12.x | bash
RUN curl 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 && apt-get install -y nodejs yarn
RUN apt-get update && apt-get install -y gconf-service libasound2 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget
RUN apt-get install -y default-mysql-client

WORKDIR /app_production

RUN export RAILS_ENV=production
RUN gem install bundler:2.2.31

COPY Gemfile Gemfile.lock ./
COPY package.json ./
COPY vendor/gems/ vendor/gems/

RUN bundle install

COPY . ./

RUN yarn install --check-files

EXPOSE 5000

CMD ["RAILS_ENV=production", "bundle", "exec", "puma", "-C", "config/puma.rb"]

database.yml

default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password:

production:
  <<: *default
  host: database_production
  port: 3306
  database: db_production
  username: user
  password: "some_password"
  socket: "/var/run/mysqld/mysqld.sock"

Notes :

  • This configuration is working fine on another server on Ubuntu 22.04
  • I’m now trying to make it works on this server on Ubuntu 20.04
  • I had to add RUN apt-get install -y default-mysql-client to the Dockerfile in order to have MySQL working in the Rails container, otherwise it was not found, but on my other server I did not have to do this
  • I also had to create a shared volume for mysql_socket:/var/run/mysqld otherwise socket was not found
  • I am able to log to MySQL with CLI on the Rails container, using the same credentials
  • If I put a phpMyAdmin service in docker-compose, I am also able to login to MySQL using the same credentials
  • If I try to connect to MySQL via container’s rails console, it works
  • If I remove bundle exec rails db:create db:migrate from rails container command, rails is launched

So I don’t understand much what exactly is happening, since I can successfully connect to MySQL through container’s CLI and PhpMyAdmin.
How come Rails can’t connect to it ? There are no detailed logs.

It fails at the step rake db:create and when trying to run it manually via rails console I got the same error. Very stange.

Any clue ?

2

Answers


  1. Chosen as BEST ANSWER

    Found the solution: It was a privileges issue with the MySQL user.

    Had to connect to MySQL as root and run the following command :

    GRANT ALL PRIVILEGES ON db_production.* TO 'user'@'%';
    

  2. Setting the environment variable MYSQL_USER in the docker file just creates the user, but grants no privileges to it. To solve the problem you can create a file with the following content

    GRANT ALL PRIVILEGES ON db_production.* TO 'user'@'%';
    

    and mount it in the /docker-entrypoint-initdb.d folder. That way when mysql is run for the first time it will execute the file and grant the appropiate privileges. This way will endure any container/volume deletion as opposed to manually granting the privileges.

    Excerpt from mysql – Official Image | Docker

    Initializing a fresh instance

    When a container is started for the first time, a new database with the specified name will be created and initialized with the provided configuration variables. Furthermore, it will execute files with extensions .sh, .sql and .sql.gz that are found in /docker-entrypoint-initdb.d. Files will be executed in alphabetical order. You can easily populate your mysql services by mounting a SQL dump into that directory and provide custom images with contributed data. SQL files will be imported by default to the database specified by the MYSQL_DATABASE variable.

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