I need to setup Django + MS SQL + Python 3.6 together on a Linux Docker container.
I ran the official Docker Django + PostgreSQL guide and everything is working fine, but when I switch to using Microsoft SQL Server 2008 as the database using the django-pyodbc-azure driver, I get the error:
localhost did not send data
I would appreciate any help or guidance on this.
# settings.py
DATABASES = {
'default': {
'ENGINE': 'sql_server.pyodbc',
'HOST': 'SERVERNAME',
'NAME': 'DATABASENAME',
'USER': '',
'PASSWORD': '',
'OPTIONS': {
"driver": "FreeTDS",
"host_is_server": True,
"unicode_results": True,
"extra_params": "tds_version=8.0",
}
}
}
# docker-compose.yml
version: '3'
services:
# db:
# image: postgres
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
# Dockerfile
FROM python:3.6
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
RUN apt-get update && apt-get install -y \
unixodbc \
unixodbc-dev \
tdsodbc
RUN apt-get install -y freetds-common freetds-bin freetds-dev
ADD odbcinst.ini /etc/
RUN pip install pipenv
COPY Pipfile Pipfile.lock /code/
RUN pipenv install --system
# COPY . /code/
Do you talk to mysql over port 8000?
Try specifying that port in your Database config if you do. Mysql normally uses port 3306 so maybe try somthing like
# settings.py
DATABASES = {
'default': {
'ENGINE': 'sql_server.pyodbc',
'HOST': 'SERVERNAME',
'NAME': 'DATABASENAME',
'USER': '',
'PASSWORD': '',
'PORT': '3306',
'OPTIONS': {
"driver": "FreeTDS",
"host_is_server": True,
"unicode_results": True,
"extra_params": "tds_version=8.0",
}
}
}
You will also need to specify this in your docker compose
# docker-compose.yml
services:
# db:
# image: postgres
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
- "3306:3306"
Related
docker-compose.yml
version: "3.7"
services:
db:
platform: linux/x86_64
image: mysql:5.7
volumes:
- ./db_data1:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: "${DB_ROOT_PASSWORD}"
MYSQL_DATABASE: "${DB_DATABASE}"
MYSQL_USER: "${DB_USER}"
MYSQL_PASSWORD: "${DB_ROOT_PASSWORD}"
ports:
- 3306:3306
command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
web:
build:
dockerfile: ./Dockerfile
command: python3 manage.py runserver 0.0.0.0:8000
volumes:
- ./web_data1:/app
ports:
- 8000:8000
environment:
DJANGO_DB_HOST: db:3306
DJANGO_DB_NAME: "${DB_DATABASE}"
DJANGO_DB_USER: "${DB_USER}"
DJANGO_DB_PASSWORD: "${DB_ROOT_PASSWORD}"
my_setting.py
DATABASES = {
'default' : {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'test',
'USER': 'root',
'PASSWORD': "${DB_ROOT_PASSWORD}",
'HOST': 'db',
'PORT': '3306',
}
}
SECRET = 'django-insecure-#kb%p45em8hdhja^+2jal#(*mzw1c3jk5gvsx(_cn#q^u#u&b0'
ALGORITHM = 'HS256'
Dockerfile
FROM python:3
ENV PYTHONUNBUFFERED=1
WORKDIR /usr/src/app
COPY requirements.txt ./
RUN pip install -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "docker_train.wsgi:application"]
.env
DB_ROOT_PASSWORD=password
DB_DATABASE=test
DB_USER=root
I run docker-compose up but got this error.
How can I approach it to solve the problem?
error
docker-training11-db-1 | 2021-11-09 05:14:47+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.36-1debian10 started.
docker-training11-web-1 | Watching for file changes with StatReloader
docker-training11-web-1 | Performing system checks...
As I am able to identify, you are facing some issue with your DATABASE details. Kindly verify them first.
django is not able to resolve db host name.
instead of 'db' try passing private ip of base machine.
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.
I create a django docker application image.
in my django app, in settings.py DATABASE entry is:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'cath_local',
'USER': 'postgres',
'PASSWORD': 'mypass',
'HOST': 'postgres',
'PORT': '5432',
'OPTIONS': {
'client_encoding': 'UTF8',
},
}
}
well, at this point i create my docker image using docker build command; all done.
Before running my django app docker image i run:
docker run -it postgres
image is downloaded and container start correctly
but when i run my django app
docker run -it cath2019/cathedral_studio:latest
but wher python manage.py runserver command into my Dockerfile start i get this error:
conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
django.db.utils.OperationalError: could not translate host name "postgres" to address: Name does not resolve
here my app Dockerfile:
FROM python:3.6-alpine
RUN apk add --no-cache make linux-headers libffi-dev jpeg-dev zlib-dev
RUN apk update && apk add postgresql-dev gcc python3-dev musl-dev
#RUN apk update && apk add build-essential libssl-dev libffi-dev
RUN mkdir /Code
WORKDIR /Code
COPY ./requirements.txt .
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
ENV PYTHONUNBUFFERED 1
COPY . /Code/
ENTRYPOINT python /Code/core/manage.py runserver 0.0.0.0:8000
How can i connect into my django settings DATABASE to running postgres container?
So many thanks in advance
You can use two methods to solve this:
1. User defined networks
The default bridge network is present on all Docker hosts. If you do
not specify a different network, new containers are automatically
connected to the default bridge network.
Link
You can get IP address of containers using docker network inspect bridge.
Then you can use the IP address from containers attribute.
This is not recommended as changes in container might change the ip
address.
Docker does not support automatic service discovery on the
default bridge network. If you want containers to be able to resolve
IP addresses by container name, you should use user-defined networks
instead. You can link two containers together using the legacy docker run --link option, but this is not recommended in most cases.
To Create a network run docker network create --driver bridge django_network.
Then attach both the containers to same network using
docker run -it postgres --network=django_network and
docker run -it cath2019/cathedral_studio:latest --network=django_network.
Now you can connect to postgres database from your django app using hostname.
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'cath_local',
'USER': 'postgres',
'PASSWORD': 'mypass',
'HOST': 'postgres',
'PORT': '5432',
'OPTIONS': {
'client_encoding': 'UTF8',
},
}
}
2. Docker-compose
Have a look at official documentation Link to dockerize a django app.
version: '3'
services:
db:
image: postgres
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
depends_on:
- db
Using only Docker
You would need to link the Django container using: --link postgres:postgres
Checkout this answer
Using Docker Compose
version: '3'
services:
db:
image: postgres
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
depends_on:
- db
Source: https://docs.docker.com/compose/django/
Since I moved to Docker Postgres, my tests via pytest fail. I now identified as the problem my database connection.
How it works:
When I use PostgreSQL 10 on my Mac it works smoothly. As database credentials in my settings.py I use:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'project',
'USER': 'MyName',
'PASSWORD': '',
'HOST': '127.0.0.1',
'PORT': '5432',
}
}
How it fails: Since I moved to Docker + Postgres, I have to use different credentials to connect to my Docker Postgres:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'postgres',
'USER': 'postgres',
'HOST': 'db',
'PORT': 5432,
}
}
As I want to use Docker rather than PostgreSQL, but still want to be able to test, I wonder if you have any solution for my problem?
Here my console log output: https://pastebin.com/MZsccuGJ
My Dockerfile
# Pull base image
FROM python:3
# Set environment varibles
ENV PYTHONUNBUFFERED 1
# Set work directory
RUN mkdir /code
WORKDIR /code
# Install dependencies
RUN pip install --upgrade pip
RUN pip install pipenv
COPY ./Pipfile /code/Pipfile
RUN pipenv install --deploy --system --skip-lock --dev
# Define ENTRYPOINT
COPY ./docker-entrypoint.sh /docker-entrypoint.sh
RUN chmod +x /docker-entrypoint.sh
ENTRYPOINT ["/docker-entrypoint.sh"]
# Copy project
COPY . /code/
Docker-Compose
version: '3'
services:
db:
image: postgres
ports:
- "5432:5432"
web:
build: .
env_file: .env
volumes:
- .:/code
ports:
- "8000:8000"
depends_on:
- db
container_name: project
I am trying to migrate my Django project using MySQL database to postgresql with Docker. When I use MySQL everything works fine. I have all in ORM so when I use MySQL I have to create only database and do python manage.py makemigrations and then python manage.py migrate and I get ready database with all relations. As I have mentioned I'm trying to use postgresql database. Server seems to work fine using docker-compose up, but when I send for instance GET request I get:
ProgrammingError at /data
relation "authtoken_token" does not exist
LINE 1: ...user"."is_active", "auth_user"."date_joined" FROM "authtoken...
My settings:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'postgres',
'USER': 'postgres',
'HOST': 'db',
'PORT': 5432,
}
}
My docker-compose.yml:
version: '3'
services:
db:
image: postgres
web:
build: .
command: python3 DIR/backend/dir/manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
depends_on:
- db
Dockerfile:
FROM python:3.6.1
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
ADD requirements.txt /code/
RUN pip3 install -r requirements.txt
ADD . /code/
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f364a72186ce dockerpri_web "python3 PROJECT/backe..." 19 seconds ago Up 18 seconds 0.0.0.0:8000->8000/tcp dockerpri_web_1
774ae20bcaa3 postgres "docker-entrypoint..." 9 hours ago Up 19 seconds 5432/tcp dockerpri_db_1
MacBook-Pro:DockerPROJECT myName$ docker exec -ti dockerproject_web_1 /bin/bash
root#f364a72186ce:/code#