I am trying to connect mysql database. Here I am using two docker container one for mysql and one for rails. I am using this docker compose file:
version: '3'
services:
db:
image: mysql:5.7
restart: always
environment:
MYSQL_ROOT_PASSWORD: password
volumes:
- ./mydata:/var/lib/mysql
ports:
- "3307:3306"
web:
build: .
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- .:/myapp
ports:
- "3000:3000"
When I am running docker compose up and I can see my containers are running my docker ps command show me:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d1bc75bbb4f7 mysql "docker-entrypoint.s…" 22 seconds ago Up 19 seconds 0.0.0.0:3307->3306/tcp aaupf_db_1
2ccb0882c390 aaupf_web "bundle exec rails s…" 12 minutes ago Up 9 minutes 0.0.0.0:3000->3000/tcp aaupf_web_1
I am using this code in my database.yml:
development:
adapter: mysql2
encoding: utf8
reconnect: false
database: sample_sqlite3_development
pool: 5
username: root
password: password
host: 127.0.0.1
port: 3307
But I am getting this error in rails:
Can't connect to MySQL server on '127.0.0.1' (111 "Connection refused")
I can connect mysql using mysql workbench I don't know what do I need to do in order to connect my rails app to mysql.
Try using host: db in your database.yml. This should link your web and mysql container.
https://docs.docker.com/v17.09/compose/rails/#connect-the-database
default: &default
adapter: postgresql
encoding: unicode
host: db
username: postgres
password:
pool: 5
development:
<<: *default
database: myapp_development
test:
<<: *default
database: myapp_test
Firstly, you should check if you are able to login into mysql from console using command
mysql -u root -p
You don't need mysql workbench to connect your docker rails to local database.
For connecting to local db:
docker-compose.yml
version: '3'
services:
db:
image: mysql:5.7
restart: always
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_USER: root
MYSQL_PASSWORD: password
web:
build: .
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- .:/myapp
depends_on:
- db
network_mode: "host"
environment:
DB_USER: root
DB_PASSWORD: password
DB_HOST: 127.0.0.1
The option network_mode: "host" enables connection to local db.
config/database.yml:
default: &default
adapter: mysql2
encoding: utf8mb4
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: <%= ENV['DB_USER'] %>
password: <%= ENV['DB_PASSWORD'] %>
host: <%= ENV['DB_HOST'] %>
development:
<<: *default
Try below one:
version: '3'
services:
db:
image: mariadb
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_USERNAME: root
MYSQL_PASSWORD: root
ports:
- "3306:3306"
volumes:
- ./tmp/db_data:/var/lib/mysql/data
web:
build: .
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
volumes:
- .:/myapp
ports:
- "3000:3000"
depends_on:
- db
Related
I’m on Mac OS Big Sur and running the following Docker versions
$ docker -v
Docker version 20.10.12, build e91ed57
$ docker-compose -v
Docker Compose version v2.2.3
I’m running a Rails 6 app, whose database is configured like so
development:
adapter: mysql2
encoding: utf8
host: host.docker.internal
database: cfs
pool: 5
username: myuser
password: bypass
I have to use “host.docker.internal” so that the Rails app can access the Docker db when running inside of Docker, set up in my docker-compose.yml like so
services:
db:
image: mysql:5.7
command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
restart: always
volumes:
- ./docker/provision/mysql/init:/docker-entrypoint-initdb.d
environment:
MYSQL_ROOT_PASSWORD: bypass
ports:
# <Port exposed> : < MySQL Port running inside container>
- '3306:3306'
expose:
# Opens port 3306 on the container
- '3306'
…
web:
#restart: always
build: ./my-project
ports:
- "3000:3000"
expose:
- '3000'
command: foreman start
volumes:
- ./my-project/:/app
depends_on:
- db
However if I run the app locally without Docker, I have to change my config files to remove “host.docker.internal” and use “127.0.0.1” instead (or localhost).
Is there a way I can set things up so that I have a single database config file that works in both Docker and without Docker such that I don’t have to change the host around?
You can use ERB markup in the database.yml file, which lets you use an environment variable here. In general I'd suggest making default values for things be whatever default will work in a plain non-Docker development environment.
# config/database.yml
development:
host: <%= ENV['DATABASE_HOST'] || 'localhost' %>
If you're running this in a setup where the database hostname isn't localhost – it's in a sibling container, or you're using a cloud-hosted database like Amazon RDS – you can set that environment variable.
# docker-compose.yml
version: '3.8'
services:
db:
image: 'mysql:5.7'
et: cetera
web:
build: .
ports:
- '3000:3000'
depends_on:
- db
environment:
DATABASE_HOST: db # <-- will be read in database.yml
I'm trying to have a docker container use my local mysql database. Using docker-compose up, I am able to get all the pieces running, however, the db exits with status code 1, and the rails application cannot connect to any database instance. I know that mysql is running on my system and that the service has been started. My docker-compose file:
version: '3'
services:
db:
image: mysql
restart: always
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: db
MYSQL_USER: root
MYSQL_PASSWORD: password
volumes:
- ./tmp/db:/var/lib/mysql
web:
build: .
image: rails-devise:1.0.0
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
volumes:
- ".:/baas-status"
ports:
- "3000:3000"
depends_on:
- db
I know the containers are running because docker ps gives the following output:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1a49aba0cd68 rails-devise:1.0.0 "entrypoint.sh bash …" 23 minutes ago Up 2 minutes 0.0.0.0:3000->3000/tcp status_web_1
38554baf5efc mysql "docker-entrypoint.s…" 23 minutes ago Up 2 minutes 3306/tcp, 0.0.0.0:3002->3002/tcp, 33060/tcp status_db_1
Even though I exposed port 3002 and want to use that as the port for the database, is it unable to connect because I'm on the wrong port? I see in the docker ps output that mysql is on port 3306.
My database.yml file:
base: &base
adapter: mysql2
encoding: utf8
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
default: &default
<<: *base
username: <%= ENV['DB_USERNAME'] %>
password: <%= ENV['DB_PASSWORD'] %>
host: <%= ENV['DB_HOST'] %>
database: <%= ENV['DB_NAME'] %>
development:
<<: *base
username: root
password: password
host: db
database: db
I have also tried editing the host for development to be host: db. That didn't change anything either. I tried running docker-compose run web rake db:create as well, and I get the following error:
This has been fixed with the current changes to the docker-compose file
Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)
At this point, I'm at a loss on where to proceed. Any information or help would be greatly appreciated. Thank you.
Edit:
I have changed the ports for the db and it seems to have fixed the connection issues. Now I'm running into an error that gives
web_1 | Mysql2::Error::ConnectionError (Plugin caching_sha2_password could not be loaded: /usr/lib/x86_64-linux-gnu/mariadb19/plugin/caching_sha2_password.so: cannot open shared object file: No such file or directory):
I'm going to do some research to figure out the meaning behind this error, any tips to move in the right direction would be greatly appreciated though!
Edit2:
I ended up connecting the db by reverting mysql back to 5.7.18 to avoid the sha authentication. The docker-compose file and settings that worked for me are as follows:
docker-compose.yml
version: '2'
services:
db:
image: mysql:5.7.18
restart: always
ports:
- 3306:3306
environment:
- MYSQL_ROOT_PASSWORD=root
volumes:
- db-data:/var/lib/mysql
web:
build: .
image: rails-devise:1.0.0
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
volumes:
- ".:/baas-status"
ports:
- 3000:3000
links:
- db
depends_on:
- db
volumes:
db-data:
driver: local
The database.yml file remained the same with the exception of changing the password to root. This is the solution that worked for me.
Resource I ended up using!
Sounds like you figured out the connection issue. You'll want to connect on 3306, not 3002 based on the docker-compose file you posted.
I assume you also made sure to define these environment variables in your rails docker container as well. Is that correct?
username: <%= ENV['DB_USERNAME'] %>
password: <%= ENV['DB_PASSWORD'] %>
host: <%= ENV['DB_HOST'] %>
database: <%= ENV['DB_NAME'] %>
Since you do not define a tag of the mysql image to use in your docker-compose file, it will pull the latest image which is mysql ~8.x. MySQL 8 uses the caching_sha2_password authentication plugin by default (unless you specify otherwise). The Rails mysql2 driver version you're using likely does not support this authentication mechanism yet.
So, if you would like to revert to an older authentication plugin (like the one from mysql 5.7), you can use a command line flag in your mysql container like so:
services:
...
db:
image: mysql:8.0
...
command: mysqld --default-authentication-plugin=mysql_native_password
More information can also be found on this SO answer.
I am running into this error with my Rails + MySQL Docker setup:
Mysql2::Error::ConnectionError: Unknown MySQL server host 'db' (-2)
/usr/local/bundle/gems/mysql2-0.5.2/lib/mysql2/client.rb:90:in `connect'
/usr/local/bundle/gems/mysql2-0.5.2/lib/mysql2/client.rb:90:in `initialize'
my docker-compose.yml:
version: '3.7'
services:
db:
# https://github.com/passbolt/passbolt_docker/issues/103
image: mysql:5.7
restart: always
healthcheck:
test: ["CMD-SHELL", 'mysql --database=$$MYSQL_DATABASE --password=$$MYSQL_ROOT_PASSWORD --execute="SELECT count(table_name) > 0 FROM information_schema.tables;" --skip-column-names -B']
interval: 30s
timeout: 10s
retries: 4
environment:
MYSQL_DATABASE: 'db'
MYSQL_USER: 'user'
MYSQL_PASSWORD: 'password'
MYSQL_ROOT_PASSWORD: 'password'
ports:
- "3305:3306"
expose:
- '3305'
volumes:
- my-db:/var/lib/mysql
web:
build: .
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
volumes:
- '.:/app'
ports:
- '3000:3000'
environment:
DB_PORT: 3306
DB_HOST: db
DATABASE_URL: mysql2://user:password#db:3306
depends_on:
- db
volumes:
my-db:
and my database.yml:
default: &default
adapter: mysql2
encoding: utf8mb4
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: user
password: password
host: localhost
url: <%= ENV['DATABASE_URL'] %>
port: 3305
According to this, I'm supposed to wait for MySQL to start? However I added a health check in the healthcheck section of the docker-compose file and it didn't work.
I also tried to use netcat to check the port but it also didn't work. How come I can't connect to the host db from my Docker web container? What am I doing wrong?
Turns out for my problem, I needed to clear out my docker volumes and recreate everything. MySQL was experiencing an error while booting up.
Basically ran this:
docker-compose down
docker system prune --force --volumes
And then restarted everything, ensuring that MySQL ("db") was running successfully before trying to connect to db.
This message is complaining about a missing "MYSQL host" called 'db'
Mysql2::Error::ConnectionError: Unknown MySQL server host 'db' (-2)
According to your docker-compose file
environment:
MYSQL_DATABASE: 'db'
MYSQL_USER: 'user'
MYSQL_PASSWORD: 'password'
MYSQL_ROOT_PASSWORD: 'password'
You should choose here a valid parameters (use ENV variables even better).
Also make sure
you can access MYSQL from console with the specified credintials.
The specified MYSQL user has access from external host ( docker is will not be on the same network )
I'm new to docker, I am trying to create a virtual docker image in ruby using mysql database and the docker image need to execute in different systems. it is possible to build the docker image without Docker-compose.yml (by using docker build or CMD) please help me in this.
My Dockerfile
FROM ruby:2.5
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp
and my Docker-compose.yml
version: '3'
services:
db:
image: mysql:5.7
restart: always
environment:
MYSQL_ROOT_PASSWORD: letmein
MYSQL_DATABASE: myapp
MYSQL_USER: appuser
MYSQL_PASSWORD: letmein
ports:
- "3307:3306"
app:
build: .
command: bundel exec rails s -p 3000 -b '0.0.0.0'
volumes:
- ".:/myapp"
ports:
- "3001:3000"
depends_on:
- db
links:
- db
environment:
DB_USER: root
DB_NAME: myapp
DB_PASSWORD: letmein
DB_HOST: db
database.yml
default: &default
adapter: mysql2
encoding: utf8
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
database: <%= ENV['DB_NAME'] %>
username: <%= ENV['DB_USER'] %>
password: <%= ENV['DB_PASS'] %>
host: <%= ENV['DB_HOST'] %>
development:
<<: *default
database: myapp_development
test:
<<: *default
database: myapp_test
production:
<<: *default
database: myapp_production
username: myapp
password: <%= ENV['MYAPP_DATABASE_PASSWORD'] %>
I am trying to connect my rails app which is on my host to docker mysql image. But I am getting this error:
Authentication plugin 'caching_sha2_password' cannot be loaded: dlopen(/usr/local/Cellar/mysql/5.7.22/lib/plugin/caching_sha2_password.so, 2): image not found
My Docker compose file is like this:
db:
image: mysql
restart: always
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: password
adminer:
image: adminer
restart: always
ports:
- 8080:8080
I am using this inside my database.yml:
default: &default
adapter: mysql2
encoding: utf8
host: 127.0.0.1
username: root
password: password
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
# socket: /Applications/MAMP/tmp/mysql/mysql.sock
development:
<<: *default
database: meal_plan_development
What else I should do in order to connect my rails app to mysql docker image.
MySQL default-authentication-plugin
as of version 8, MySQL uses caching_sha2_password as the default authentication plugin. You can override it to use mysql_native_password by adding a command instruction in your docker-compose.yml file like this:
db:
image: mysql
command: --default-authentication-plugin=mysql_native_password
restart: always
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: password
adminer:
image: adminer
restart: always
ports:
- 8080:8080
As #vstm pointed out, this seems to be the same problem I was having with a PHP client. After the container has been created you could try changing the authentication scheme to one which will likely be supported e.g.
docker exec <container_id> /bin/sh -c "mysql -uroot -ppassword
-e ALTER USER root#localhost IDENTIFIED WITH mysql_native_password BY 'PASSWORD'"
I'm not overly familiar with Docker, but I believe you can also add something like this to a Dockerfile so that the authentication method will be changed during the container initialization:
RUN /bin/bash -c "mysql -uroot -ppassword
-e ALTER USER root#localhost IDENTIFIED WITH mysql_native_password BY 'PASSWORD'"