django cannot connect mysql in docker-compose - mysql

I'm very new for docker, now I am trying to run django with mariadb in docker through docker-compose, but I always get this error:
I use Docker version 17.09.1-ce, build 19e2cf6, docker-compose version 1.18.0, build 8dd22a9
django.db.utils.OperationalError: (2003, 'Can\'t connect to MySQL
server on \'mariadb55\' (111 "Connection refused")')
I can connect db correctly after run docker-compose up db in local or remote, and I even can run python manage.py runserver 0.0.0.0:6001 correctly in anaconda virtual environment to connect db service in docker by setting parameters of settings.py file like below:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'test',
'USER': 'belter',
# 'HOST': 'mariadb55',
'HOST': '127.0.0.1',
'PORT': '3302',
'PASSWORD': 'belter_2017',
'default-character-set': 'utf8',
'OPTIONS': {
'sql_mode': 'traditional',
}
}
}
This is my docker-compose.yml file
version: '3'
services:
db:
image: mariadb:5.5
restart: always
environment:
- MYSQL_HOST=localhost
- MYSQL_PORT=3306
- MYSQL_ROOT_HOST=%
- MYSQL_DATABASE=test
- MYSQL_USER=belter
- MYSQL_PASSWORD=belter_2017
- MYSQL_ROOT_PASSWORD=123456_abc
volumes:
- /home/belter/mdbdata/mdb55:/var/lib/mysql
ports:
- "3302:3306"
web:
image: onlybelter/django_py35
command: python3 manage.py runserver 0.0.0.0:6001
volumes:
- /mnt/data/www/mysite:/djcode
ports:
- "6001:6001"
depends_on:
- db
links:
- db:mariadb55
I almost tried everything I can find, but still cannot figure it out, any help would be nice!
What I have tried:
Docker compose mysql connection failing
Linking django and mysql containers using docker-compose
Django connection to postgres by docker-compose

Finally, I figured it out!
The key point is, just as #SangminKim said, I need to use 3306 not 3302 in settings.py, and use db as HOST not 127.0.0.1.
So this is my docker-compose.yml file now:
version: '3'
services:
db:
image: mariadb:5.5
restart: always
environment:
- MYSQL_HOST=localhost
- MYSQL_PORT=3306 # cannot change this port to other number
- MYSQL_ROOT_HOST=%
- MYSQL_DATABASE=test
- MYSQL_USER=belter
- MYSQL_PASSWORD=belter_2017
- MYSQL_ROOT_PASSWORD=123456_abc
volumes:
- /home/belter/mdbdata/mdb55:/var/lib/mysql
ports:
- "3302:3306"
web:
image: onlybelter/django_py35
command: python3 manage.py runserver 0.0.0.0:6001
volumes:
- .:/djcode
ports:
- "6001:6001"
depends_on:
- db
So now we can connect this docker-mysql by mysql -h 127.0.0.1 -P 3302 -u root -p in shell directly, but we have to use db and 3306 in django settings.py file:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'test',
'USER': 'belter',
# 'HOST': 'mariadb55',
'HOST': 'db', #<---
'PORT': '3306', #<---
'PASSWORD': 'belter_2017',
'default-character-set': 'utf8',
'OPTIONS': {
'sql_mode': 'traditional',
}
}
}
And we can still check if this port is open, by running extra command in docker-compose.yml file:
...
web:
image: onlybelter/django_py35
command: /bin/sh -c "python check_db.py --service-name mysql --ip db --port 3306"
volumes:
- .:/djcode
...
Here is check_db.py file:
# check_db.py
import socket
import time
import argparse
""" Check if port is open, avoid docker-compose race condition """
parser = argparse.ArgumentParser(description='Check if port is open, avoid\
docker-compose race condition')
parser.add_argument('--service-name', required=True)
parser.add_argument('--ip', required=True)
parser.add_argument('--port', required=True)
args = parser.parse_args()
# Get arguments
service_name = str(args.service_name)
port = int(args.port)
ip = str(args.ip)
# Infinite loop
while True:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
result = sock.connect_ex((ip, port))
if result == 0:
print("{0} port is open! Bye!".format(service_name))
break
else:
print("{0} port is not open! I'll check it soon!".format(service_name))
time.sleep(3)
By the way, this is my Dockerfile for build django-py35:
FROM python:3.5-alpine
MAINTAINER Xin Xiong "xiongxin20008#126.com"
ENV PYTHONUNBUFFERED 1
RUN set -e; \
apk add --no-cache --virtual .build-deps \
gcc \
libc-dev \
linux-headers \
mariadb-dev \
python3-dev \
postgresql-dev \
freetype-dev \
libpng-dev \
g++ \
;
RUN mkdir /djcode
WORKDIR /djcode
ENV REFRESHED_AT 2017-12-25
ADD requirements.txt /djcode/
RUN pip install --no-cache-dir -r /djcode/requirements.txt
RUN pip install uwsgi
ADD . /djcode/ # copy . to /djcode/
EXPOSE 6001
See more details from here: https://github.com/OnlyBelter/django-compose

You should use the container name instead of localhost (or 127.0.0.1) in your settings.py file. Try providing a container name to the db service in the docker-compose.yml file using container_name attribute and replace the host name in the settings.py by the value of the container_name. (Make sure that they are in the same network that docker compose creates for you.)

Build container with this:
docker run --name mysql-latest \
-p 3306:3306 -p 33060:33060 \
-e MYSQL_ROOT_HOST='%' -e MYSQL_ROOT_PASSWORD='strongpassword' \
-d mysql/mysql-server:latest
Make sure MYSQL_ROOT_HOST='%', that means root can connect from any IP.

Related

How to run Sequelize migrations inside Docker

I'm trying to docerize my NodeJS API together with a MySQL image. Before the initial run, I want to run Sequelize migrations and seeds to have the tables up and ready to be served.
Here's my docker-compose.yaml:
version: '3.8'
services:
mysqldb:
image: mysql
restart: unless-stopped
environment:
MYSQL_ROOT_USER: myuser
MYSQL_ROOT_PASSWORD: mypassword
MYSQL_DATABASE: mydb
ports:
- '3306:3306'
networks:
- app-connect
volumes:
- db-config:/etc/mysql
- db-data:/var/lib/mysql
- ./db/backup/files/:/data_backup/data
app:
build:
context: .
dockerfile: ./Dockerfile
image: node-mysql-app
depends_on:
- mysqldb
ports:
- '3030:3030'
networks:
- app-connect
stdin_open: true
tty: true
volumes:
db-config:
db-data:
networks:
app-connect:
driver: bridge
Here's my app's Dockerfile:
FROM node:lts-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3030
ENV PORT 3030
ENV NODE_ENV docker
RUN npm run db:migrate:up
RUN npm run db:seeds:up
CMD [ "npm", "start" ]
And here's my default.db.json that the Sequelize migration uses (shortened):
{
"development": {
},
"production": {
},
"docker": {
"username": "myuser",
"password": "mypassword",
"database": "mydb",
"host": "mysqldb",
"port": "3306",
"dialect": "mysql"
}
}
Upon running compose up the DB installs well, the image deploys, but when it reaches the RUN npm run db:migrate:up (which translates into npx sequelize-cli db:migrate) I get the error:
npx: installed 81 in 13.108s
Sequelize CLI [Node: 14.17.0, CLI: 6.2.0, ORM: 6.6.2]
Loaded configuration file "default.db.json".
Using environment "docker".
ERROR: getaddrinfo EAI_AGAIN mysqldb
npm ERR! code ELIFECYCLE
npm ERR! errno 1
If I change the "host" in the default.db.json to "127.0.0.1", I get ERROR: connect ECONNREFUSED 127.0.0.1:3306 in place of the ERROR: getaddrinfo EAI_AGAIN mysqldb.
What am i doing wrong, and what host should I specify so the app can see the MySQL container? Should I remove the network? Should I change ports? (I tried combinations of both to no avail, so far).
I solved my issue by using Docker Compose Wait. Essentially, it adds a wait loop that samples the DB container, and only when it's up, runs migrations and seeds the DB.
My next problem was: those seeds ran every time the container was run - I solved that by instead running a script that runs the seeds, and touchs a semaphore file. If the file exists already, it skips the seeds.
The following configuration worked for me, I am adding the .env, sequelize configuration along with mysql database and docker. And finally don't forget to run docker-compose up --build cheers 🎁 🎁 🎁
.env
DB_NAME="testdb"
DB_USER="root"
DB_PASS="root"
DB_HOST="mysql"
.sequelizerc now we can use config.js rather than config.json for sequelize
const path = require('path');
module.exports = {
'config': path.resolve('config', 'config.js')
}
config.js
require("dotenv").config();
module.exports = {
development: {
username: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_NAME,
host: process.env.DB_HOST,
dialect: "mysql"
},
test: {
username: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_NAME,
host: process.env.DB_HOST,
dialect: "mysql"
},
production: {
username: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_NAME,
host: process.env.DB_HOST,
dialect: "mysql"
}
}
database-connection with sequelize
import Sequelize from 'sequelize';
import dbConfig from './config/config';
const conf = dbConfig.development;
const sequelize = new Sequelize(
conf.database,
conf.username,
conf.password,
{
host: conf.host,
dialect: "mysql",
operatorsAliases: 0,
logging: 0
}
);
sequelize.sync();
(async () => {
try {
await sequelize.authenticate();
console.log("Database connection setup successfully!");
} catch (error) {
console.log("Unable to connect to the database", error);
}
})();
export default sequelize;
global.sequelize = sequelize;
docker-compose.yaml
version: "3.8"
networks:
proxy:
name: proxy
services:
mysql:
image: mysql
networks:
- proxy
ports:
- 3306:3306
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=testdb
healthcheck:
test: "mysql -uroot -p$$MYSQL_ROOT_PASSWORD -e 'SHOW databases'"
interval: 10s
retries: 3
api:
build: ./node-backend
networks:
- proxy
ports:
- 3000:3000
depends_on:
mysql:
condition: service_healthy
Dockerfile
FROM node:16
WORKDIR /api
COPY . /api
RUN npm i
EXPOSE 3000
RUN chmod +x startup.sh
RUN npm i -g sequelize-cli
RUN npm i -g nodemon
ENTRYPOINT [ "./startup.sh" ]
startup.sh
#!/bin/bash
npm run migrate-db
npm run start
I found a really clean solution wanted to share it. First of all I used docker-compose, so if you are using only docker, it might not help.
First thig first, I created a docker file which looks like that.I am using typescript, so if you are using js, you don't need to download typescript and build it!
FROM node:current-alpine
WORKDIR /app
COPY . ./
COPY .env.development ./.env
RUN npm install
RUN npm install -g typescript
RUN npm install -g sequelize-cli
RUN npm install -g nodemon
RUN npm run build
RUN rm -f .npmrc
RUN cp -R res/ dist/
RUN chmod 755 docker/entrypoint.sh
EXPOSE 8000
EXPOSE 3000
EXPOSE 9229
CMD ["sh", "-c","--","echo 'started';while true; do sleep 1000; done"]
Till here it is standart. In order to do things in right order, I need a docker compose and entrypoint file. Entrypoint file is a file, that runs when your containers start. Here is docker-compose file.
version: '3'
services:
app:
build:
context: ..
dockerfile: docker/Dockerfile.development
entrypoint: docker/development-entrypoint.sh
ports:
- 3000:3000
env_file:
- ../.env.development
depends_on:
- postgres
postgres:
image: postgres:alpine
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=test
volumes:
- ./docker_postgres_init.sql:/docker-entrypoint-initdb.d/docker_postgres_init.sql
As you can see, I am using postgresql for db. My docker file, docker-compose and also entrypoint files are in a folder called docker, thats why the paths starts wtih docker, change it according to your file structure. Last and the best part is the entrypoint file. It is really simple.
#!/bin/sh
echo "Starting get ready!!!"
sequelize db:migrate
nodemon ./dist/index.js
Ofcourse change the path of the index.js file according to your settings.
Hope it helps!

Dockerize Django project with MySQL container [duplicate]

I'm trying to connect Django project with MySQL using docker.
I have the problem when upping docker-compose. It says the next error:
super(Connection, self).init(*args, **kwargs2)
django.db.utils.OperationalError: (2002, "Can't connect to MySQL server on 'db' (115)")
I'm using port 3307, should i create first new database schema in my local? Or how can I do it because my default port is 3306 but if i try to use it, it says that is busy.
My code here:
Dockerfile
FROM python:3.7
ENV PYTHONUNBUFFERED 1
ENV LANG=C.UTF-8
RUN mkdir /code
WORKDIR /code
ADD requirements.txt /code/
RUN apt-get update
RUN pip install -r requirements.txt
ADD . /code/
Docker-compose
version: '2'
services:
app:
container_name: container_app
build:
context: .
dockerfile: Dockerfile
restart: always
command: bash -c "python3 manage.py migrate && python manage.py shell < backend/scripts/setup.py && python3 manage.py runserver 0.0.0.0:8000"
links:
- db
depends_on:
- db
ports:
- "8000:8000"
db:
container_name: container_database
image: mariadb
restart: always
environment:
MYSQL_ROOT_HOST: 'host.docker.internal'
MYSQL_DATABASE: 'container_develop'
MYSQL_USER: 'root'
MYSQL_PASSWORD: 'password'
MYSQL_ROOT_PASSWORD: 'password'
ports:
- "3307:3307"
settings.py:
DATABASES = {
'default' : {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'database_develop',
'USER': 'root',
'PASSWORD': 'password',
'HOST': 'db',
'PORT': 3307,
'CHARSET': 'utf8',
'COLLATION': 'utf8_bin',
'OPTIONS': {
'use_unicode' : True,
'init_command': 'SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED',
},
}
}
The thing is that I do not have the database anywhere so I'm using it locally, do I have to upload the db to a server and then use the port that server provides to me?
Is there any way to use it locally from docker? Or installing it to docker? So I can share that docker to a friend and he can use the same DB?
In the "db" part, in your docker-compose :
ports:
- "3307:3306"
The #Nico answer my fixed your service accessibility from outside of the container, mean if try to access it from the host it should work.
But the error will arise during service to service communication. You should not use publish port in service to service communication or another word you must use container port in service to service communication.
Change the port in connection from 3307 to 3306
DATABASES = {
'default' : {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'database_develop',
'USER': 'root',
'PASSWORD': 'password',
'HOST': 'db',
'PORT': 3306,
'CHARSET': 'utf8',
'COLLATION': 'utf8_bin',
'OPTIONS': {
'use_unicode' : True,
'init_command': 'SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED',
},
}
}

Django can not connect to MySQL container?

I have a docker-compose like a bellow:
version: '3'
services:
mysql:
image: mysql
ports:
- 3306:3306
env_file: ./src/.environment
volumes:
- mysql_data:/var/lib/mysql
web:
build:
context: ./src
dockerfile: Dockerfile
command: bash -c "python manage.py collectstatic --no-input && python manage.py makemigrations --no-input && python manage.py migrate --no-input"
env_file: ./src/.environment
ports:
- 8001:8001
depends_on:
- mysql
volumes:
- ./src:/var/www/project/src
- staticfiles:/var/www/project/src/statics
.environment content as follow:
DATABASE_MYSQL_NAME=dataCollection
DATABASE_MYSQL_HOST=mysql
DATABASE_MYSQL_USER=user1
DATABASE_MYSQL_PASSWORD=user123456
DATABASE_MYSQL_PORT=3306
Then in django setting I have follow database configuration:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': os.getenv('DATABASE_MYSQL_NAME'),
'HOST': os.getenv('DATABASE_MYSQL_HOST'),
'USER': os.getenv('DATABASE_MYSQL_USER'),
'PASSWORD': os.getenv('DATABASE_MYSQL_PASSWORD'),
'PORT': os.getenv('DATABASE_MYSQL_PORT'),
}
}
But, when I run docker-comose up it throws the following error:
MySQLdb._exceptions.OperationalError: (2002, "Can't connect to MySQL server on 'mysql' (115)")
I don't know what the problem is?

Windows Docker Can't connect to local MySQL server through socket

I have a project on windows Docker, when I run the docker-compose up, it gives me the bellow error
php_1 | Database tma not reachable at host: localhost for user: drupal
php_1 | ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/run/mysqld/mysqld.sock' (2)
Here is the docker-compose.yml
version: "3"
services:
mariadb:
image: wodby/mariadb:$MARIADB_TAG
container_name: "${PROJECT_NAME}_mariadb"
stop_grace_period: 30s
environment:
MYSQL_ROOT_PASSWORD: $DB_ROOT_PASSWORD
MYSQL_DATABASE: $DB_NAME
MYSQL_USER: $DB_USER
MYSQL_PASSWORD: $DB_PASSWORD
volumes:
- ./dev_tools/mariadb-init:/docker-entrypoint-initdb.d # Place init .sql file(s) here.
php:
image: wodby/drupal-php:$PHP_TAG
container_name: "${PROJECT_NAME}_php"
environment:
PHP_SENDMAIL_PATH: /usr/sbin/sendmail -t -i -S mailhog:1025
# PHP_SENDMAIL_PATH: /usr/sbin/sendmail -t -i -S opensmtpd:25
DB_HOST: $DB_HOST
DB_PORT: $DB_PORT
DB_USER: $DB_USER
DB_PASSWORD: $DB_PASSWORD
DB_NAME: $DB_NAME
DB_DRIVER: $DB_DRIVER
PHP_FPM_USER: wodby
PHP_FPM_GROUP: wodby
COLUMNS: 80 # Set 80 columns for docker exec -it.
volumes:
- ./:/var/www/html/
command: sh /var/www/html/dev_tools/php-entrypoint.bash
apache:
image: wodby/apache:$APACHE_TAG
container_name: "${PROJECT_NAME}_apache"
depends_on:
- php
environment:
APACHE_LOG_LEVEL: debug
APACHE_BACKEND_HOST: php
APACHE_VHOST_PRESET: php
APACHE_DOCUMENT_ROOT: /var/www/html/docroot
volumes:
- ./:/var/www/html
labels:
- "traefik.http.routers.${PROJECT_NAME}_apache.rule=Host(`${PROJECT_BASE_URL}`)"

Docker-Compose can't connect to MySQL

I'm trying to connect Django project with MySQL using docker.
I have the problem when upping docker-compose. It says the next error:
super(Connection, self).init(*args, **kwargs2)
django.db.utils.OperationalError: (2002, "Can't connect to MySQL server on 'db' (115)")
I'm using port 3307, should i create first new database schema in my local? Or how can I do it because my default port is 3306 but if i try to use it, it says that is busy.
My code here:
Dockerfile
FROM python:3.7
ENV PYTHONUNBUFFERED 1
ENV LANG=C.UTF-8
RUN mkdir /code
WORKDIR /code
ADD requirements.txt /code/
RUN apt-get update
RUN pip install -r requirements.txt
ADD . /code/
Docker-compose
version: '2'
services:
app:
container_name: container_app
build:
context: .
dockerfile: Dockerfile
restart: always
command: bash -c "python3 manage.py migrate && python manage.py shell < backend/scripts/setup.py && python3 manage.py runserver 0.0.0.0:8000"
links:
- db
depends_on:
- db
ports:
- "8000:8000"
db:
container_name: container_database
image: mariadb
restart: always
environment:
MYSQL_ROOT_HOST: 'host.docker.internal'
MYSQL_DATABASE: 'container_develop'
MYSQL_USER: 'root'
MYSQL_PASSWORD: 'password'
MYSQL_ROOT_PASSWORD: 'password'
ports:
- "3307:3307"
settings.py:
DATABASES = {
'default' : {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'database_develop',
'USER': 'root',
'PASSWORD': 'password',
'HOST': 'db',
'PORT': 3307,
'CHARSET': 'utf8',
'COLLATION': 'utf8_bin',
'OPTIONS': {
'use_unicode' : True,
'init_command': 'SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED',
},
}
}
The thing is that I do not have the database anywhere so I'm using it locally, do I have to upload the db to a server and then use the port that server provides to me?
Is there any way to use it locally from docker? Or installing it to docker? So I can share that docker to a friend and he can use the same DB?
In the "db" part, in your docker-compose :
ports:
- "3307:3306"
The #Nico answer my fixed your service accessibility from outside of the container, mean if try to access it from the host it should work.
But the error will arise during service to service communication. You should not use publish port in service to service communication or another word you must use container port in service to service communication.
Change the port in connection from 3307 to 3306
DATABASES = {
'default' : {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'database_develop',
'USER': 'root',
'PASSWORD': 'password',
'HOST': 'db',
'PORT': 3306,
'CHARSET': 'utf8',
'COLLATION': 'utf8_bin',
'OPTIONS': {
'use_unicode' : True,
'init_command': 'SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED',
},
}
}