Django and Postgres problems with dockerizing - python

Hello I can not dockerize my django app because I got an error -
listen tcp4 0.0.0.0:5433: bind: address already in use
From the other hand, when I "kill" 5433 port in ubuntu terminal I get this error
Is the server running on host "localhost" (::1) and accepting
web_1 | TCP/IP connections on port 5433?
What can I do to solve this problem and dockerize successfully my app?
Dockerfile
FROM python:3
RUN adduser --system --no-create-home django
ENV PYTHONUNBUFFERED=1
WORKDIR /code
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
ENV PYTHONPATH /code
EXPOSE 8000
USER django
CMD ["./main.py"]
docker-compose
version: "3"
services:
db:
image: postgres
volumes:
- ./data/db:/var/lib/postgresql/data
environment:
- POSTGRES_DB=fitshop
- POSTGRES_USER=fituser
- POSTGRES_PASSWORD=fitpass
ports:
- "5433:5433"
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
restart: always
ports:
- "8000:8000"
depends_on:
- db
settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'fitshop',
'USER': 'fituser',
'PASSWORD': 'fitpass',
'HOST': 'localhost',
'PORT': '5433',
}
}

You should use "db" as host here. In a docker-compose setup each service is started in a separate Container and the /etc/hosts config of all containers is modified so, that each container can find the other containers via the service names.

I`ve got it!. In 'localhost" port of postgres was 5433 but for 'db' as HOST it was default, 5432.

Related

docker-compose up error for django and mysql

I am trying to configure Django and MySql application with Docker containers.
For Django I am using python:3.7-slim image and for MySql mysql:5.6.
When I run docker-compose up it returns an error stated below -
ERROR: for app_mysql_db_1 Cannot start service mysql_db: driver failed programming external connectivity on endpoint app_mysql_db_1 (c647d4793a198af2c09cc52d08191fb2cd984025ad0a61434ad1577d9dcccebe): Error starting userland proxy: listen tcp 0.0.0.0:3306: bind: address already in use
I run command docker ps -a to check docker status and found that mysql container was created but the python container status was exited.
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7d91795e0bae mysql:5.6 "docker-entrypoint.s…" 15 seconds ago Created app_mysql_db_1
fa0419ad0f21 e0bf94710555 "/bin/sh -c 'adduser…" 2 minutes ago Exited (1) 2 minutes ago pedantic_faraday
can someone rewrite or suggest the modification for the configurations.
Dockerfile
FROM python:3.7-slim
ENV PYTHONUNBUFFERED 1
RUN apt-get update
RUN apt-get install python3-dev default-libmysqlclient-dev gcc -y
COPY ./requirements.txt /requirements.txt
RUN pip install -r /requirements.txt
RUN mkdir /app
WORKDIR /app
COPY . /app
docker-compose.yaml
version: "3"
services:
eitan-application:
restart: always
build:
context: .
ports:
- "8000:8000"
volumes:
- ./eitan:/app
command: >
sh -c "python3 manage.py runserver 0.0.0.0:8000
&& python3 manage.py makemigrations
&& python3 manage.py migrate"
depends_on:
- mysql_db
mysql_db:
image: mysql:5.6
command: mysqld --default-authentication-plugin=mysql_native_password
volumes:
- "./mysql:/var/lib/mysql"
ports:
- "3306:3306"
restart: always
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=root
- MYSQL_USER=root
- MYSQL_PASSWORD=root
settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'my-app-db',
'USER': 'root',
'PASSWORD': 'root',
'HOST': 'mysql_db',
'PORT': 3307,
}
}
bind: address already in use suggests that you have some local database running. If you don't need to access database outside of docker-compose network don't expose port 3306. So I'd try to test it without
...
ports:
- "3306:3306"
...
Also in settings.py you connect to port mysql_db:3307 so change it to default port 3306.
Even if you expose database port to some other port on localhost then settings.py connects using mysql_db network, so you shouldn't change this port in django settings.

How can I set the best configurations for the project working with django, docker and mysql?

I was reading an article in here which is about setting up project using docker, django and mysql together.
these are my files in project:
Dockerfile
FROM python:3.7
MAINTAINER masoud masoumi moghadam
ENV PYTHONUNBUFFERED 1
RUN mkdir /app
WORKDIR /app
ADD . /app
ADD requirements.txt /app/requirements.txt
RUN pip install --upgrade pip && pip install -r requirements.txt
Docker-compose
version: "3"
services:
app:
build:
context: .
ports:
- "8000:8000"
volumes:
- ./app:/app
command: >
sh -c "python manage.py runserver 0.0.0.0:8000"
environment:
- DB_HOST=localhost
- DB_NAME=contact_list
- DB_USER=root
- DB_PASS=secretpassword
depends_on:
- db
db:
image: mysql:5.7
environment:
- MYSQL_DATABASE=contact_list
- MYSQL_USER=root
- MYSQL_PASSWORD=secretpassword
requirements
Django>=2.0,<3.0
djangorestframework<3.10.0
mysqlclient==1.3.13
django-mysql==2.2.0
and also this settings in my setting.py:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': os.environ.get('DB_HOST'),
'NAME': os.environ.get('DB_NAME'),
'USER': os.environ.get('DB_USER'),
'PASSWORD': os.environ.get('DB_PASS')
}
}
When I use docker-compose build I face no problem and everything is just fine. Then I run service mysql start. I can assure that mysql service is in run and works because I have access to datasets. The problem occurs when I do the migration using this command docker-compose run app sh -c "python manage.py makemigrations core" I get this error:
django.db.utils.OperationalError: (2002,
"Can't connect to local MySQL server through socket
'/var/run/mysqld/mysqld.sock' (2)")
When I change localhost to 127.0.0.1 I get this error:
django.db.utils.OperationalError:
(2002, "Can't connect to MySQL
server on '127.0.0.1' (115)")
I spent 20 hours looking for the best possible configuration for these technologies, But I still can't figure out anything. I also used python-alpine but I still could not find it useful for project because I had the same mysql dependencies problem when I was trying to do docker build. Does anybody have the same experience? I would appreciate if you could help me here.
Your problem is that you use localhost as the host of mysql in django's config.
But docker containers have their own IP, they are not localhost.
So first in your docker-compose file, name your containers :
db:
image: mysql:5.7
container_name: db
...
Then in your django settings, set your db HOST to your db container name : "db" :
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': 'db',
'PORT' : 3306, # (?)
...
Also you are missing the db 'PORT' in django settings, I think that for Mysql it is 3306 (I've added it above).
According to this beautifully organized article, I found out this configurations will have no issues running on a server(changed mysql service to postgress service):
Dockerfile
# pull official base image
FROM python:3.8.0-alpine
# set work directory
WORKDIR /usr/src/app
# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# install psycopg2 dependencies
RUN apk update \
&& apk add postgresql-dev gcc python3-dev musl-dev
# install dependencies
RUN pip install --upgrade pip
COPY requirements.txt /usr/src/app/requirements.txt
RUN pip install -r requirements.txt
# copy entrypoint.sh
COPY entrypoint.sh /usr/src/app/entrypoint.sh
# copy project
COPY . /usr/src/app/
# run entrypoint.sh
ENTRYPOINT ["/usr/src/app/entrypoint.sh"]
Docker-compose.yml
version: '3.7'
services:
web:
build: app
# container_name: web
command: python manage.py runserver 0.0.0.0:8000
restart: always
volumes:
- ./app/:/usr/src/app/
ports:
- 8000:8000
env_file:
- .env.dev
depends_on:
- db
db:
image: postgres:12.0-alpine
# container_name: postgres
restart: always
volumes:
- postgres_data:/var/lib/postgresql/data/
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=123456
- POSTGRES_DB=contact_list
requirements
Django==2.2.6
gunicorn==19.9.0
djangorestframework>=3.9.2,<3.10.0
psycopg2-binary==2.8.3
settings
DATABASES = {
'default': {
'ENGINE': os.environ.get('SQL_ENGINE', "django.db.backends.sqlite3"),
'NAME': os.environ.get("SQL_DB_NAME", os.path.join(BASE_DIR, "db.sqlite3")),
'USER': os.environ.get("SQL_USER", "user"),
'PASSWORD': os.environ.get("SQL_PASSWORD", "password"),
'HOST': os.environ.get("SQL_HOST", "localhost"),
'PORT': os.environ.get("SQL_PORT", "5432"),
}
}
I added a file named as .env.dev which is for better access to environment variables:
DEBUG=1
SECRET_KEY=123456
DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1]
SQL_ENGINE=django.db.backends.postgresql
SQL_HOST=db
SQL_DB_NAME=contact_list
SQL_USER=user
SQL_PASSWORD=123456
SQL_PORT=5432
DATABASE=postgres
first try to login to mysql with provided credentials
docker exec -it <CONTAINER_ID> /bin/sh
Inside the docker please login to mysql via command line
mysql -uroot -psecretpassword

Dockerizing Django App

I have a Django application that uses Python 2.7.10 and Django 1.10.3. My Dockerfile contains the following:
FROM python:2.7.10
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
ADD requirements.txt /code/
RUN pip install -r requirements.txt
ADD . /code/
My requirements.txt contains the following:
Django>=1.10,<2.0
Mysql-python
My docker-compose.yml contains the following:
version: '2'
services:
localhost:
image: mysql
restart: always
environment:
MYSQL_DATABASE: 'test'
MYSQL_USER: 'test'
MYSQL_PASSWORD: 'password'
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
depends_on:
- localhost
settings.py contains the following for the database:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'test',
'USER': 'test',
'PASSWORD': 'password',
'HOST': 'localhost',
'PORT': '3306',
}
I first do a "% docker-compose build", then I do a "% docker-compose up" and get the following error:
web_1 | django.db.utils.OperationalError: (2002, "Can't connect
to local MySQL server through socket '/var/run/mysqld/mysqld.sock'
I've looked and tried the solutions available on Stackoverflow with no luck. Any help would be much appreciated.
Any help would be much appreciated.
In regards to MySql and Django App relation you have three possible cases:
MySql is residing on same container as Django App (localhost)
MySql is residing on separate container from Django App (hostname is different, can be handled on different topology - same subnet or different etc)
MySql is residing outside of docker ecosystem (bare metal, cloud, whatever...)
Judging from your settings.py and docker-compose.yml you are mixing first two approaches. Now, since you can reference external MySql server from settings.py I'll consider that case trivial, next, cramming MySql on same container as Django App is usually bad idea (if you ever want to scale them separately) so this answer will focus on second case (MySql in separate container) and, for simplicity, on same docker-compose file (you can separate them as well).
Important excerpt from docker-compose.yml is:
version: '2'
services:
# The Database
database:
image: mysql:5.6
volumes:
- dbdata:/var/lib/mysql
environment:
- "MYSQL_DATABASE=test_db"
- "MYSQL_USER=test_user"
- "MYSQL_PASSWORD=some_password"
- "MYSQL_ROOT_PASSWORD=some_root_password"
ports:
- "33061:3306"
container_name: "mysql_database"
# Django App (taken from your example, added env vars as hint)
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
environment:
- "DB_PORT=3306"
- "DB_HOST=database"
volumes:
- .:/code
ports:
- "8000:8000"
depends_on:
- database
volumes:
dbdata:
With such docker-compose you would have following setting.py config (note that HOST is taking value of docker-compose service entry for database container, port is internal to container not external to docker-host):
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'test_db',
'USER': 'test_user',
'PASSWORD': 'some_password',
'HOST': 'database',
'PORT': '3306',
}
As a sidenote, we usually run database with separate docker-compose.yml from Django App file since in usual dev cycle it is far more frequent to tweak/restart/crash something on Django App container than on database one and we can handle it separately that way, plus such a separately defined database can handle several different DjangoApps each with its own container.

Django connection to postgres by docker-compose

My django project cannot connect to postgres database container. What I should to do?
It crashes on commands python manage.py collectstatic --noinput && python manage.py makemigrations blog && python manage.py migrate.
I know docker run command creates a new container but I have more commands as
one by bash in docker-compose.yml. It should works, shouldn't it?
my Dockerfile:
FROM python:3.6-alpine
MAINTAINER Name <name#domain>
ENV PYTHONUNBUFFERED 1
ENV INSTALL_PATH /heckblog
RUN mkdir -p $INSTALL_PATH
WORKDIR $INSTALL_PATH
COPY requirements.txt requirements.txt
# make available run pip install psycopg2
RUN apk update && \
apk add --virtual build-deps gcc python3-dev musl-dev && \
apk add postgresql-dev
RUN pip3 install -r requirements.txt
# add bash into alpine linux
RUN apk add --update bash && rm -rf /var/cache/apk/*
COPY ./heckblog .
#RUN pip install .
CMD gunicorn -b 0.0.0.0:8000 --access-logfile - "config.wsgi:application"
my docker-compose.yml:
version: '2'
services:
db:
image: postgres:alpine
environment:
POSTGRES_USER: blogdmin
POSTGRES_PASSWORD: password
POSTGRES_DB: heckblog
PGDATA: /tmp/pgdata
volumes:
- postgres_data:/tmp/pgdata
web:
build: .
command: >
bash -c "sleep 10 &&
python manage.py collectstatic --noinput &&
python manage.py makemigrations blog &&
python manage.py migrate &&
echo \"from django.contrib.auth.models import User; User.objects.create_superuser('admin', 'admin#example.com', 'pass')\" | python manage.py shell &&
gunicorn -b 0.0.0.0:8000 --access-logfile - --reload \"config.wsgi:application\""
volumes:
- ./heckblog:/heckblog
depends_on:
- db
environment:
IN_DOCKER: 1
ports:
- "80:8000"
volumes:
postgres_data:
settings.py:
...
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'heckblog',
'USER': 'blogdmin',
'PASSWORD': 'password',
'HOST': 'localhost',
'PORT': '', # default port
}
}
...
Output of docker-compose up --build:
web_1 | TCP/IP connections on port 5432?
web_1 | could not connect to server: Connection refused
web_1 | Is the server running on host "localhost" (127.0.0.1) and accepting
web_1 | TCP/IP connections on port 5432?
web_1 |
heckblog_web_1 exited with code 1
I use:
Windows 10
Docker 17.03.0-ce-win1-(10296)
docker-compose version 1.11.2
Django==1.10.6
psycopg2==2.7.1.
Thanks for answers
Each container in docker by default gets its own hostname and IP. When compose spins up the containers for you, it also places all of the containers on a network by default to permit DNS based discovery.
What this means is that your database is not reachable on localhost, but you can reach it by the service name "db". Change this line in your settings.py:
'HOST': 'localhost',
to:
'HOST': 'db',
Here's what worked for me:
in compose:
version: '3.7'
services:
web:
build: .
command: python /code/manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- 8000:8000
environment:
- DB_HOST=db
- DB_NAME=web
- DB_USER=postgres
- DB_PASSWORD=postgres
depends_on:
- db
db:
image: postgres:12-alpine
volumes:
- postgres_data:/var/lib/postgresql/data/
environment:
- POSTGRES_DB=web
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
volumes:
postgres_data:
in settings:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ.get('DB_NAME'),
'USER':os.environ.get('DB_USER'),
'PASSWORD': os.environ.get('DB_PASSWORD'),
'HOST':os.environ.get('DB_HOST'),
'PORT':5432,
}
}
Django settings.py -> Database={host:db} . Other database option remain same. Like
DATABASE_ENGINE=django.db.backends.postgresql
DATABASE_USER=postgres
DATABASE_PASSWORD=1234
DATABASE_NAME=pos
DATABASE_HOST=db
DATABASE_PORT=5432
Docker compose yml file: This settings created for Django, Nginx, Postgres
version: '3.8'
services:
nginx:
restart: unless-stopped
build:
context: .
dockerfile: ./docker/nginx/Dockerfile
ports:
- '81:81'
volumes:
- static_volume:/home/pos/static/
- ./docker/nginx/development:/etc/nginx/conf.d
depends_on:
- backend
backend:
restart: unless-stopped
build:
context: .
dockerfile: ./docker/backend/Dockerfile
image: pos-backend:backend # image_name: image_tag
container_name: pos_backend
volumes:
- ./backend:/home/pos/
- static_volume:/home/pos/static
- media_volume:/home/pos/media
environment:
DJANGO_SETTINGS_MODULE: pos.settings
ports:
- "8000:8000"
command: python manage.py runserver 0.0.0.0:8000
expose:
- 8000
env_file:
- ./backend/.env.dev
depends_on:
- db
db:
image: postgres:12
container_name: pos_db
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=1234
- POSTGRES_DB=pos
ports:
- '5432:5432'
expose:
- 5432
networks:
- default
volumes:
static_volume: {}
media_volume:
postgres_data:

Docker Django could not connect to server: Connection refused

I'm new to Docker, and I'm trying to put my Django rest API in a container with Nginx, Gunicorn and Postgres, using docker-compose and docker-machine. Following this tutorial: https://realpython.com/blog/python/django-development-with-docker-compose-and-machine/
Most of my code is the same as the tutorial's (https://github.com/realpython/dockerizing-django). with some minor name changes.
this my docker-compose.yml (I changed the gunicorn command to runserver for debugging purposes)
web:
restart: always
build: ./web
expose:
- "8000"
links:
- postgres:postgres
- redis:redis
volumes:
- /usr/src/app
- /usr/src/app/static
env_file: .env
environment:
DEBUG: 'true'
command: /usr/local/bin/python manage.py runserver
nginx:
restart: always
build: ./nginx/
ports:
- "80:80"
volumes:
- /www/static
volumes_from:
- web
links:
- web:web
postgres:
restart: always
image: postgres:latest
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data/
redis:
restart: always
image: redis:latest
ports:
- "6379:6379"
volumes:
- redisdata:/data
And this is in my settings.py of Django:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'postgres',
'USER': 'postgres',
'PASSWORD': 'postgres',
'HOST': 'postgres',
'PORT': '5432',
}
}
Nginx and postgres (and redis) are up and running, however my django server wont start, by this error:
web_1 | django.db.utils.OperationalError: could not connect to server: Connection refused
web_1 | Is the server running on host "localhost" (::1) and accepting
web_1 | TCP/IP connections on port 5432?
web_1 | could not connect to server: Connection refused
web_1 | Is the server running on host "localhost" (127.0.0.1) and accepting
web_1 | TCP/IP connections on port 5432?
I've googled a lot and I've verified that postgres is running, on port 5432, I can connect to it using psql command .
I am lost. What is my mistake?
EDIT: It appears that it is not using my settings.py file or something, since it's asking if the server is running on localhost, while settings should be looking for postgres.
When those who have this problem please check your settings.py:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'dbname',
'USER': 'user',
'PASSWORD': 'password',
'HOST': 'db'
}
}
Your HOST:'db' and docker-compose file db name should be same. If you want to rename from db, make sure that you change in docker-compose file and setting.py:
db:
restart: always
image: postgres:latest
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data/
Checkout your manage.py,
there should be a line
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myproject.settings")
if there is no such line, put it
set your DJANGO_SETTINGS_MODULE with respect to PYTHONPATH.
UPD i cloned your repo and launched the web service by changing command in docker-compose.yml
- command: /usr/local/bin/gunicorn docker_django.wsgi:application -w 2 -b :8000
+ command: python manage.py runserver 0.0.0.0:8000
I'm sure DJANGO_SETTINGS_MODULE is correct.
I'm exactly facing the same issue, while runing my django app with docker on aws ec2 instance.
I noticed that this error only happend for the first time the docker image is build, so to fix i juste ran :
CTRL + C then docker-compose up again and everything worked fine.

Categories