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
Found the solution: It was a privileges issue with the MySQL user.
Had to connect to MySQL as root and run the following command :
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 contentand 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