My docker contianer django server, postgres, celery worker and celery beat. Running the application by itself there is no issue with connecting to the database however when the timed task to update the database runs I get an error
celery_1 | django.db.utils.OperationalError: could not connect to server: No such file or directory
celery_1 | Is the server running locally and accepting
celery_1 | connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?
below are my files
docker-compose.yaml
version: "3"
services:
redis:
image: redis:alpine
db:
image: postgres:10-alpine
environment:
- POSTGRES_DB=app
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=supersecretpassword
ports:
- "5432:5432"
volumes:
- "db:/var/lib/postgresql/data"
pgadmin:
image: dpage/pgadmin4
depends_on:
- db
ports:
- "5555:80"
environment:
- PGADMIN_DEFAULT_EMAIL=dev#localhost
- PGADMIN_DEFAULT_PASSWORD=password
dj-dividend:
container_name: dividend
build: backend
command: sh -c "python manage.py wait_for_db && python manage.py makemigrations && python manage.py migrate && python manage.py runserver 0.0.0.0:80"
environment:
- DB_HOST=db
- DB_NAME=app
- DB_USER=postgres
- DB_PASS=supersecretpassword
volumes:
- ./backend:/code
ports:
- "80:80"
depends_on:
- db
- redis
celery:
build: backend
command: celery -A backend worker -l info
volumes:
- ./backend:/code
depends_on:
- db
- redis
celery-beat:
build: backend
command: celery -A backend beat -l info
volumes:
- ./backend:/code
depends_on:
- db
- redis
- celery
volumes:
db:
settings.py
import os
from celery.schedules import crontab
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '1a0#6lsfxtfrt0n=#q1&up6hf$px-$ug^n%^v!n)^iwp_n*7c%'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = ['*']
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'dividends',
'rest_framework',
'django_celery_beat',
'core'
]
CORS_ORIGIN_ALLOW_ALL = True
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'corsheaders.middleware.CorsMiddleware',
]
ROOT_URLCONF = 'backend.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'backend.wsgi.application'
# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'HOST': os.environ.get('DB_HOST'),
'NAME': os.environ.get('DB_NAME'),
'USER': os.environ.get('DB_USER'),
'PASSWORD': os.environ.get('DB_PASS'),
}
}
# Password validation
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/
STATIC_URL = '/static/'
#Celery
CELERY_BROKER_URL = "redis://redis:6379"
CELERY_RESULT_BACKEND = "redis://redis:6379"
CELERY_ACCEPT_CONTENT = ['application/json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_BEAT_SCHEDULE = {
"get_stocks": {
'task': 'dividends.tasks.get_stocks',
'schedule': crontab(minute="*/1") #every minute
}
}
Dockerfile
FROM python:3.7
# Set environment variables
ENV PYTHONUNBUFFERED 1
COPY requirements.txt /
# Install dependencies.
RUN pip install -r /requirements.txt
# Set work directory.
RUN mkdir /code
WORKDIR /code
# Copy project code.
COPY . /code/
EXPOSE 80
tasks.py
from celery import shared_task
from .utils import get_stock_data
from .models import Stock
#shared_task(default_retry_delay=5, max_retries=3)
def get_stocks():
for stock in Stock.objects.all().values_list('ticker'):
try:
get_stock_data(stock[0])
except:
continue
celery.py
from celery import Celery
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'backend.settings')
app = Celery('backend')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()
you need to add environment variables of the postgresql to the celery-beat
In your database container you set :
environment:
- POSTGRES_DB=app
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=supersecretpassword
Then you need to copy and paste these lines in your celery_beat container so that it can connect to your database.
You'd then get:
celery-beat:
build: backend
command: celery -A backend beat -l info
volumes:
- ./backend:/code
depends_on:
- db
- redis
- celery
environment:
- POSTGRES_DB=app
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=supersecretpassword
Related
I've seen other posts about this such as here but I still can't figure out my issue.
File structure of relevant files:
ba_django_project
| docker-compose.prod.yml
|
|__app
| Dockerfile.prod
| manage.py
| .env.prod
|
|__ba_django_project
| __init__.py
| settings.py
| wsgi.py
docker-compose.prod.yml:
version: '3.8'
services:
web:
build:
context: ./app
dockerfile: Dockerfile.prod
image: 370950449536.dkr.ecr.us-east-2.amazonaws.com/ba_django_project:ba_django_project_web
command: gunicorn ba_django_project.wsgi:application --bind 0.0.0.0:8000
volumes:
- static_volume:/home/app/web/staticfiles
- media_volume:/home/app/web/mediafiles
expose:
- 8000
env_file:
- ./app/.env.prod
depends_on:
- db
db:
image: postgres:13.0-alpine
volumes:
- postgres_data:/var/lib/postgresql/data/
env_file:
- ./app/.env.prod.db
nginx:
build: ./nginx
image: 370950449536.dkr.ecr.us-east-2.amazonaws.com/ba_django_project:ba_django_project_nginx
volumes:
- static_volume:/home/app/web/staticfiles
- media_volume:/home/app/web/mediafiles
ports:
- 1337:80
depends_on:
- web
volumes:
postgres_data:
static_volume:
media_volume:
settings.py:
from pathlib import Path
from decouple import config
import os
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
STATIC_DIR = os.path.join(BASE_DIR, "static")
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.environ.get('SECRET_KEY')
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = int(os.environ.get("DEBUG", default=0))
ALLOWED_HOSTS = [
'ec2-3-20-22-254.us-east-2.compute.amazonaws.com', '0.0.0.0', 'localhost', '127.0.0.1'
]
# Application definition
INSTALLED_APPS = [
'crispy_forms',
'users.apps.UsersConfig',
'resume.apps.ResumeConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
# etc. can post full version if needed
.env.prod:
SECRET_KEY='secretkeyfiller'
manage.py:
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
def main():
"""Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ba_django_project.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()
wsgi.py
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ba_django_project.settings')
application = get_wsgi_application()
I wasn't getting this error before I started trying to get the app to run on a server. Only possible solutions it seems are either I messed up something with DJANGO_SETTINGS_MODULE or there's some sort or circular dependency I can't find. I've looked through all my files to try to find files importing settings and I took out their references to settings and it still won't work.
You must have messed up with your SECRET_KEY while you were trying to secure it using .env.
You must have an actual secret key. E.g: SECRET_KEY=QhJgFHhvNJFFHjFfdH....in the.env file. If you don't have it, there are ways to generate it using this guide
NOTE: no quotes around the secret key in the .env file.
Although I could have sworn I double checked this, when I went to echoed my .env file into my server, the special characters in the secret key caused it to skip that line. This can help with inputting special characters using sed.
If that wasn't the issue, I also removed the quotes around my secret key.
I was reading William S. Vincent's book Django for Professionals book, and I tried to deploy a django app to heroku, but static folder location fails while deploying this app, i am using Docker and whitenoise package for handling the static files, here important information in files.
settings.py
import dj_database_url
import socket
from pathlib import Path
import os
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Este cambio es para el despliegue en heroku, ya que hay problemas con los archivos estáticos
# para más información vea: https://devcenter.heroku.com/articles/django-assets
#BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# El entorno, producción vs desarrollo
ENVIRONMENT = os.environ.get('ENVIRONMENT', default='production')
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.environ.get('SECRET_KEY')
# SECURITY WARNING: don't run with debug turned on in production!
# por defecto 0, ya que el proyecto estará pronto en producción
DEBUG = int(os.environ.get('DEBUG', default=0))
ALLOWED_HOSTS = ['aplicacion-de-ventas.herokuapp.com',
'localhost', '127.0.0.1']
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'whitenoise.runserver_nostatic',
'django.contrib.staticfiles',
'django.contrib.sites',
# 3rd party
'crispy_forms',
'allauth',
'allauth.account',
'allauth.socialaccount',
'allauth.socialaccount.providers.github',
'allauth.socialaccount.providers.google',
'debug_toolbar',
# local apps
'pages.apps.PagesConfig',
'ventas.apps.VentasConfig',
'perfiles.apps.PerfilesConfig',
]
MIDDLEWARE = [
'django.middleware.cache.UpdateCacheMiddleware',
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'debug_toolbar.middleware.DebugToolbarMiddleware',
'django.middleware.cache.FetchFromCacheMiddleware',
]
# Configuración de CACHE
CACHE_MIDDLEWARE_ALIAS = 'default'
CACHE_MIDDLEWARE_SECONDS = 604800
CACHE_MIDDLEWARE_KEY_PREFIX = ''
ROOT_URLCONF = 'clothes_shop_project.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates'), ],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'clothes_shop_project.wsgi.application'
# Database
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'postgres',
'USER': 'postgres',
'PASSWORD': 'postgres',
'HOST': 'db',
'PORT': 5432
}
}
# Password validation
# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/3.1/topics/i18n/
LANGUAGE_CODE = 'es'
TIME_ZONE = 'America/Lima'
USE_I18N = True
USE_L10N = True
# si esto permanece en False considera correctamente el tiempo de America/Lima
# si esto está en True considera el timezone en UTC
USE_TZ = False
# django crispy_forms
CRISPY_TEMPLATE_PACK = 'bootstrap4'
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.1/howto/static-files/
STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static'), ]
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATICFILES_FINDERS = [
"django.contrib.staticfiles.finders.FileSystemFinder",
"django.contrib.staticfiles.finders.AppDirectoriesFinder",
]
# redirections when a user login or logout of our app
LOGIN_REDIRECT_URL = "pages:bienvenida"
LOGOUT_REDIRECT_URL = "pages:bienvenida"
# configuraciones para enviar correos electrónicos de cambio de contraseña
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
DEFAULT_FROM_EMAIL = os.environ.get('DEFAULT_FROM_EMAIL')
EMAIL_HOST = os.environ.get('EMAIL_HOST')
EMAIL_HOST_USER = os.environ.get('EMAIL_HOST_USER')
EMAIL_HOST_PASSWORD = (
os.environ.get('EMAIL_HOST_PASSWORD')
)
EMAIL_PORT = os.environ.get('EMAIL_PORT')
EMAIL_USE_TLS = True
# allauth configuration
SITE_ID = 1
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'allauth.account.auth_backends.AuthenticationBackend',
)
SOCIALACCOUNT_PROVIDERS = {
'google': {
'SCOPE': [
'profile',
'email',
],
'AUTH_PARAMS': {
'access_type': 'online',
}
}
}
ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_AUTHENTICATION_METHOD = 'email'
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_UNIQUE_EMAIL = True
ACCOUNT_EMAIL_VERIFICATION = 'mandatory'
# django-debug-toolbar
hostname, _, ips = socket.gethostbyname_ex(socket.gethostname())
INTERNAL_IPS = [ip[:-1] + "1" for ip in ips]
# production
if ENVIRONMENT == 'production':
SECURE_BROWSER_XSS_FILTER = True
X_FRAME_OPTIONS = 'DENY'
SECURE_SSL_REDIRECT = True
SECURE_HSTS_SECONDS = 3600
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
SECURE_CONTENT_TYPE_NOSNIFF = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
# Heroku
db_from_env = dj_database_url.config(conn_max_age=500)
DATABASES['default'].update(db_from_env)
docker-compose.yml
version: '3.8'
services:
web:
build: .
# command: python /code/manage.py runserver 0.0.0.0:8001
command: gunicorn clothes_shop_project.wsgi -b 0.0.0.0:8001
environment:
- ENVIRONMENT=development
- SECRET_KEY=<secret_key>
- DEFAULT_FROM_EMAIL=<email>
- EMAIL_HOST=smtp.sendgrid.net
- EMAIL_HOST_USER=apikey
- EMAIL_HOST_PASSWORD=<email_host_password>
- EMAIL_PORT=<port>
- DEBUG=1
volumes:
- .:/code
ports:
- 8001:8001
depends_on:
- db
db:
image: postgres:11
volumes:
- postgres_data:/var/lib/postgresql/data/
environment:
- "POSTGRES_HOST_AUTH_METHOD=trust"
volumes:
postgres_data:
docker-compose-prod.yml
version: '3.8'
services:
web:
build: .
# command: python /code/manage.py runserver 0.0.0.0:8001
command: gunicorn clothes_shop_project.wsgi -b 0.0.0.0:8001
environment:
- ENVIRONMENT=production
- SECRET_KEY=71dmqf6x1k^bnns1p!kkld7tq%=p!s)%r&f5h2y#^eq4h8i86$$
- DEFAULT_FROM_EMAIL=luckly083#gmail.com
- EMAIL_HOST=smtp.sendgrid.net
- EMAIL_HOST_USER=apikey
- EMAIL_HOST_PASSWORD=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
- EMAIL_PORT=587
- DEBUG=0
ports:
- 8001:8001
depends_on:
- db
db:
image: postgres:11
environment:
- "POSTGRES_HOST_AUTH_METHOD=trust"
Dockerfile
# Pull base image
FROM python:3.8
# Set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# Set work directory
WORKDIR /code
# Install dependencies
COPY Pipfile Pipfile.lock /code/
RUN pip install --upgrade pip
RUN pip install pipenv && pipenv install --system
# Copy project
COPY . /code/
heroku.yml
setup:
addons:
- plan: heroku-postgresql
build:
docker:
web: Dockerfile
release:
image: web
command:
- python manage.py collectstatic --noinput
run:
web: gunicorn clothes_shop_project.wsgi
The problem occurs when i execute python manage.py collectstatic --noinput and the errors that console shows me are these:
2021-03-18T23:01:40.412515+00:00 app[release.7010]: Traceback (most recent call last):
2021-03-18T23:01:40.412541+00:00 app[release.7010]: File "manage.py", line 22, in <module>
2021-03-18T23:01:40.412547+00:00 app[release.7010]: main()
2021-03-18T23:01:40.412548+00:00 app[release.7010]: File "manage.py", line 18, in main
2021-03-18T23:01:40.412644+00:00 app[release.7010]: execute_from_command_line(sys.argv)
2021-03-18T23:01:40.412646+00:00 app[release.7010]: File "/usr/local/lib/python3.8/site-packages/django/core/management/__init__.py", line 401, in execute_from_command_line
2021-03-18T23:01:40.413128+00:00 app[release.7010]: utility.execute()
2021-03-18T23:01:40.413149+00:00 app[release.7010]: File "/usr/local/lib/python3.8/site-packages/django/core/management/__init__.py", line 395, in execute
2021-03-18T23:01:40.413422+00:00 app[release.7010]: self.fetch_command(subcommand).run_from_argv(self.argv)
2021-03-18T23:01:40.413423+00:00 app[release.7010]: File "/usr/local/lib/python3.8/site-packages/django/core/management/base.py", line 330, in run_from_argv
2021-03-18T23:01:40.413711+00:00 app[release.7010]: self.execute(*args, **cmd_options)
2021-03-18T23:01:40.413811+00:00 app[release.7010]: File "/usr/local/lib/python3.8/site-packages/django/core/management/base.py", line 371, in execute
2021-03-18T23:01:40.414107+00:00 app[release.7010]: output = self.handle(*args, **options)
2021-03-18T23:01:40.414108+00:00 app[release.7010]: File "/usr/local/lib/python3.8/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 194, in handle
2021-03-18T23:01:40.414353+00:00 app[release.7010]: collected = self.collect()
2021-03-18T23:01:40.414354+00:00 app[release.7010]: File "/usr/local/lib/python3.8/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 109, in collect
2021-03-18T23:01:40.414518+00:00 app[release.7010]: for path, storage in finder.list(self.ignore_patterns):
2021-03-18T23:01:40.414519+00:00 app[release.7010]: File "/usr/local/lib/python3.8/site-packages/django/contrib/staticfiles/finders.py", line 130, in list
2021-03-18T23:01:40.414613+00:00 app[release.7010]: for path in utils.get_files(storage, ignore_patterns):
2021-03-18T23:01:40.414614+00:00 app[release.7010]: File "/usr/local/lib/python3.8/site-packages/django/contrib/staticfiles/utils.py", line 23, in get_files
2021-03-18T23:01:40.414811+00:00 app[release.7010]: directories, files = storage.listdir(location)
2021-03-18T23:01:40.414811+00:00 app[release.7010]: File "/usr/local/lib/python3.8/site-packages/django/core/files/storage.py", line 316, in listdir
2021-03-18T23:01:40.414998+00:00 app[release.7010]: for entry in os.scandir(path):
2021-03-18T23:01:40.415096+00:00 app[release.7010]: FileNotFoundError: [Errno 2] No such file or directory: '/code/static'
If you have not solved this?
This worked for me.
In your settings.py, remove these lines:
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static'), ]
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
and Replace it with
PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
STATIC_ROOT = os.path.join(PROJECT_ROOT, 'staticfiles')
then create a folder called "static" and create a file and name it .any_thing_you_like, else it will not save.
Ps note: don't forget to import os
Ps note: I will advice you use whitenoise for your path finder
I want to use cronjob to run a script, which is to fetch data from news api and feed it into postegres which is located in other container.
so the simplified architecture is
app(in container) -> postegres(in container)
the cronjob script is inside app, and it will fetch data and then send to postegres.
in my crontab is
* * * * * cd /tourMamaRoot/tourMama/cronjob && fetch_news.py >> /var/log/cron.log 2>&1
i can run it successfully by manually run the script, but when i put it in crontab , it shows the error.
File "/usr/local/lib/python3.6/dist-packages/django/db/backends/base/base.py", line 195, in connect
self.connection = self.get_new_connection(conn_params)
File "/usr/local/lib/python3.6/dist-packages/django/db/backends/postgresql/base.py", line 178, in get_new_connection
connection = Database.connect(**conn_params)
File "/usr/local/lib/python3.6/dist-packages/psycopg2/__init__.py", line 126, in connect
conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
django.db.utils.OperationalError: could not connect to server: No such file or directory
Is the server running locally and accepting
connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?
seems it only look for database locally if use crontab, how can i set it to put data into other container like i manually run the script?
Info:
my docker container for app is Ubuntu version 18.04 , and the following is my docker file for app
FROM ubuntu:18.04
MAINTAINER Eson
ENV PYTHONUNBUFFERED 1
ENV DEBIAN_FRONTEND=noninteractive
EXPOSE 8000
# Setup directory structure
RUN mkdir /tourMamaRoot
WORKDIR /tourMamaRoot/tourMama/
COPY tourMama/requirements/base.txt /tourMamaRoot/base.txt
COPY tourMama/requirements/dev.txt /tourMamaRoot/requirements.txt
# install Python 3
RUN apt-get update && apt-get install -y \
software-properties-common
RUN add-apt-repository ppa:deadsnakes/ppa
RUN apt-get update && apt-get install -y \
python3.7 \
python3-pip
RUN python3.7 -m pip install pip
RUN apt-get update && apt-get install -y \
python3-distutils \
python3-setuptools
# install Postgresql
RUN apt-get -y install wget ca-certificates
RUN wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -
RUN sh -c echo deb http://apt.postgresql.org/pub/repos/apt/ `lsb_release -cs`-pgdg main >> /etc/apt/sources.list.d/pgdg.list
RUN apt-get update
RUN apt-get install -y postgresql postgresql-contrib
# Install some dep
RUN apt-get install net-tools
RUN apt-get install -y libpq-dev python-dev
RUN pip3 install -r /tourMamaRoot/requirements.txt
# Copy application
COPY ./tourMama/ /tourMamaRoot/tourMama/
docker compose file:
version: '3'
services:
app:
build:
# current directory
# if for dev, need to have Dockerfile.dev in folder
dockerfile: docker/dev/Dockerfile
context: .
ports:
#host to image
- "8000:8000"
volumes:
# map directory to image, which means if something changed in
# current directory, it will automatically reflect on image,
# don't need to restart docker to get the changes into effect
- ./tourMama:/tourMamaRoot/tourMama
command: >
sh -c "python3 manage.py wait_for_db &&
python3 manage.py makemigrations &&
python3 manage.py migrate &&
python3 manage.py runserver 0.0.0.0:8000 &&
sh initial_all.sh"
environment:
- DB_HOST=db
- DB_NAME=app
- DB_USER=postgres
- DB_PASS=supersecretpassword
depends_on:
- db
- redis
db:
image: postgres:11-alpine
ports:
#host to image
- "5432:5432"
environment:
- POSTGRES_DB=app
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=supersecretpassword
redis:
image: redis:5.0.5-alpine
ports:
#host to image
- "6379:6379"
# command: ["redis-server", "--appendonly", "yes"]
# hostname: redis
# networks:
# - redis-net
# volumes:
# - redis-data:/data
and my cronjob script is:
import os
import sys
import django
from django.db import IntegrityError
from newsapi.newsapi_client import NewsApiClient
sys.path.append("../")
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "tourMama.settings")
django.setup()
from news.models import News
from tourMama_app.models import Category
from config.script import categorization_loader
load_category = categorization_loader.load_category_data("catagorization.yml")
categories = list(load_category.keys())
countries = ["us", "gb"]
# Init
newsapi = NewsApiClient(api_key='secret')
for category in categories:
for country in countries:
category_lower = category.lower()
category_obj = Category.objects.filter(
category=category,
).get()
top_headlines = newsapi.get_top_headlines(q='',
# sources=object'bbc-news,the-verge',
category=category_lower,
language='en',
page_size=100,
country=country
)
for article in top_headlines.get("articles"):
try:
News.objects.create(
source=article["source"].get("name") if article["source"] else None,
title=article.get("title"),
author=article.get("author"),
description=article.get("description"),
url=article.get("url"),
urlToImage=article.get("urlToImage"),
published_at=article.get("publishedAt"),
content=article.get("content"),
category=category_obj
)
except IntegrityError:
print("data already exist")
else:
print("data insert successfully")
and if needed, my django setting file is as following:
"""
Django settings for tourMama project.
Generated by 'django-admin startproject' using Django 2.2.1.
For more information on this file, see
https://docs.djangoproject.com/en/2.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.2/ref/settings/
"""
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
TEMPLATE_DIR = os.path.join(BASE_DIR,"templates")
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'd084cm20*x*&s&w)vq+7*teea540yny+fyi^dh57nxiff&a#25'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
COMPRESS_ENABLED = False
COMPRESS_CSS_HASHING_METHOD = 'content'
COMPRESS_FILTERS = {
'css':[
'compressor.filters.css_default.CssAbsoluteFilter',
'compressor.filters.cssmin.rCSSMinFilter',
],
'js':[
'compressor.filters.jsmin.JSMinFilter',
]
}
HTML_MINIFY = False
KEEP_COMMENTS_ON_MINIFYING = False
ALLOWED_HOSTS = ['0.0.0.0', "127.0.0.1"]
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'channels',
'bootstrap3',
'tourMama_app',
'account',
'posts',
'group',
'news',
'statistics',
'compressor',
]
AUTH_USER_MODEL = "account.UserProfile"
MIDDLEWARE = [
'django.middleware.gzip.GZipMiddleware',
'htmlmin.middleware.HtmlMinifyMiddleware',
'htmlmin.middleware.MarkRequestMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'tourMama.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [TEMPLATE_DIR,],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages' ,
],
},
},
]
WSGI_APPLICATION = 'tourMama.wsgi.application'
ASGI_APPLICATION = 'tourMama.routing.application'
# https://stackoverflow.com/questions/56480472/cannot-connect-to-redis-container-from-app-container/56480746#56480746
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
"hosts": [('redis', 6379)],
},
},
}
# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'HOST': os.environ.get('DB_HOST'),
'NAME': os.environ.get('DB_NAME'),
'USER': os.environ.get('DB_USER'),
'PASSWORD': os.environ.get('DB_PASS')
}
}
# Password validation
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
# other finders..
'compressor.finders.CompressorFinder',
)
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': '127.0.0.1:11211',
}
}
# Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/
STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static'),]
STATIC_ROOT = os.path.join(BASE_DIR,"static_root")
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
LOGIN_REDIRECT_URL = "home:index"
LOGOUT_REDIRECT_URL = "home:index"
environment:
- DB_HOST=db
- DB_NAME=app
- DB_USER=postgres
- DB_PASS=supersecretpassword
I see that you are passing the environment variables via docker-compose like this. This is fine when the container is running the command directly inside the shell.
However, when putting it inside the crontab, the cronjob will run your command in a separate fresh shell with no environment being passed in at all.
To work around this problem, you can create a separate shell script:
cat <<EOF > /temp/script.sh
#!/bin/bash
export DB_HOST=db
export DB_NAME=app
export DB_USER=postgres
export DB_PASS=supersecretpassword
cd /tourMamaRoot/tourMama/cronjob && fetch_news.py >> /var/log/cron.log 2>&1
EOF
chmod +x /temp/script.sh
and edit your crontab like this:
* * * * * /temp/script.sh
I am creating a docker image of a Django server that uses a postgresql database to keep track of login information, uploaded/downloaded files, etc. I want the data in my database to stick around even when I exit and relaunch the docker image.
I created a docker-compose file and entrypoint file that successfully launches the server docker image and creates a volume for the database. Every tutorial that I've read online has said that having persistent data is as simple as mapping your database volume from the location you want it stored on the host to the /var/lib/postgresql/data location in the docker image.
docker-compose.yml:
version: '3.7'
services:
web:
build: ./
command: python manage.py runserver 0.0.0.0:8000
ports:
- 8000:8000
environment:
- DEBUG=1
- SECRET_KEY=foo
- SQL_ENGINE=django.db.backends.postgresql
- SQL_HOST=db
- SQL_PORT=5432
- DATABASE=postgres
depends_on:
- db
db:
image: postgres
volumes:
- ./postgres_data:/var/lib/postgresql/data/
environment:
...
ports:
- 5432:5432
volumes:
postgres_data:
docker-entrypoint.sh:
#!/bin/sh
if [ "$DATABASE" = "postgres" ]
then
echo "Waiting for postgres..."
while ! nc -z $SQL_HOST $SQL_PORT; do
sleep 0.1
done
echo "PostgreSQL started"
fi
python manage.py flush --no-input
python manage.py migrate
exec $#
Dockerfile:
FROM python:3.7.4-alpine
ARG PROJECT=MyProject
ARG PROJECT_DIR=/var/www/${PROJECT}
RUN mkdir -p $PROJECT_DIR
WORKDIR $PROJECT_DIR
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
RUN apk update \
&& apk add --virtual build-deps gcc python3-dev musl-dev \
&& apk add postgresql-dev \
&& pip install psycopg2 \
&& pip install django \
&& pip install djangorestframework \
&& pip install django-sslserver \
&& pip install djangosecure \
&& pip install psycopg2 \
&& pip install django-environ \
&& apk del build-deps
COPY . $PROJECT_DIR/
ENTRYPOINT ["/var/www/EchoNine/docker-entrypoint.sh"]
settings.py
import os
import sys
from django.conf import settings
import environ
env = environ.Env(
# set casting, default value
DEBUG=(bool, False)
)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
MEDIA_URL = 'inspections/'
TEST_ROOT = os.path.join(BASE_DIR, 'test')
if ('test' in sys.argv):
MEDIA_ROOT = os.path.join(TEST_ROOT, 'inspections')
else:
MEDIA_ROOT = os.path.join(BASE_DIR, 'inspections')
root = environ.Path(__file__) - 3 # three folder back (/a/b/c/ - 3 = /)
environ.Env.read_env(env.str('ENV_PATH', '.env.production')) # reading .env fil
SECRET_KEY = env('SECRET_KEY')
DEBUG = env('DEBUG') # This is set to False
ALLOWED_HOSTS = []
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'djangosecure',
'sslserver',
# Third-Party Apps
'rest_framework',
'rest_framework.authtoken',
# Local Apps (Your project's apps)
'MyProject.MyProject',
]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
],
}
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
MIDDLEWARE_CLASSES = (
'djangosecure.middleware.SecurityMiddleware',
)
ROOT_URLCONF = 'MyProject.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'MyProject.wsgi.application'
DATABASES = {
'default': {
'ENGINE': os.environ.get('SQL_ENGINE', 'django.db.backends.sqlite3'),
'NAME': os.environ.get('SQL_DATABASE', 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'),
}
}
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
STATIC_URL = '/static/'
When I launch the docker image, create a new super user inside the docker image (which stores data in the database), quit the docker image, and then relaunch the image, all database tables are empty again. I would expect the database to retain the database entries from the last run.
Both ./postgres_data on the host and /var/lib/postgresql/data inside the docker image seem to be initialized with files and a folder structure in them.
Can anyone tell me what I'm doing wrong? Thanks.
you delete everything by your Entrypoints since the entrypoint will start with every container operation (start/restart)
PS : manage.py flush will delete all your Data
I followed this tutorial here to setup Docker with Django. It works perfectly now and also my Postgres database seems to be installed. Where it fails for me is connecting with Postico (macOS) to my Postgres that's running in the container. Anyone who has experience in that, is it possible to connect 'from the outside' with eg. Postico to this container?
Currently I typed in:
Host localhost
User postgres
Password postgres
But I am not sure about the password, as in the tutorial I never set any.
docker-compose:
version: '3'
services:
db:
image: postgres
web:
build: .
command: python3 manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
depends_on:
- db
settings.py
"""
Django settings for composeexample project.
Generated by 'django-admin startproject' using Django 2.1.
For more information on this file, see
https://docs.djangoproject.com/en/2.1/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.1/ref/settings/
"""
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'XYZ'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = ['0.0.0.0']
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'composeexample.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'composeexample.wsgi.application'
# Database
# https://docs.djangoproject.com/en/2.1/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# Password validation
# https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/2.1/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.1/howto/static-files/
STATIC_URL = '/static/'
You said in comments:
I actually want to connect from my localhost, but not via terminal, but via Postico as I can easier edit database entries there.
If you wish to connect from localhost, you must expose the ports for pgsql.
version: '3'
services:
db:
image: postgres
expose:
- "5432"
ports:
- "5432:5432"
If you're on Linux, then you have to get your db IP with docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container_name_or_id and connect through the IP.
On Mac you can use localhost to access it.