I have Django application which has docker file and using below command to bring up the application
CMD ["gunicorn", "--bind", ":8000", "--workers", "3", "--worker-class", "uvicorn.workers.UvicornWorker", "myapplication.asgi:application"]
Would like to run one more process "task_process" which is present in the below directory structure
taskApp/
__init__.py
models.py
management/
__init__.py
commands/
__init__.py
task_process.py
How to execute task_process after loading an application ?
I tried the below shell script commands in startup.sh. But no luck
#!/bin/sh
exec gunicorn --bind :8000 --workers 3 --worker-class uvicorn.workers.UvicornWorker myapplication.asgi:application &
exec python manage.py task_process
#!/bin/sh
exec gunicorn --bind :8000 --workers 3 --worker-class uvicorn.workers.UvicornWorker myapplication.asgi:application &
python manage.py task_process
#!/bin/sh
gunicorn --bind :8000 --workers 3 --worker-class uvicorn.workers.UvicornWorker myapplication.asgi:application &
python manage.py task_process
#!/bin/sh
gunicorn --bind :8000 --workers 3 --worker-class uvicorn.workers.UvicornWorker myapplication.asgi:application
python manage.py task_process
Updated existing Docker file as below
RUN chmod +x startup.sh
CMD ["./startup.sh"]
Related
I am building a Django app with Docker. I run the command collectstatic in my entrypoint when database is ready. When I check my container, the /static/ folder is empty. Thus, Nginx cannot load the static files.
# settings.py
STATIC_URL = '/static/'
STATIC_ROOT = '/static/'
Here is my docker-compose file
version: "3.9"
services:
db:
image: postgis/postgis:14-3.3
container_name: db
volumes:
- ./data/db:/var/lib/postgresql/data
env_file:
- prod.env
backend:
container_name: backend
build:
dockerfile: ./django/Dockerfile
command: gunicorn api.wsgi:application --bind 0.0.0.0:8000
volumes:
- static:/usr/src/app/static
ports:
- "8000:8000"
env_file:
- prod.env
depends_on:
- db
nginx:
container_name: nginx
build:
dockerfile: ./nginx/Dockerfile
volumes:
- static:/usr/src/app/static
ports:
- "80:80"
depends_on:
- backend
restart: always
redis:
container_name: redis
restart: unless-stopped
image: redis:alpine
expose:
- 6379
worker:
container_name: worker
build:
dockerfile: ./django/Dockerfile
command: celery -A api worker -l INFO
volumes:
- static:/usr/src/app/static
env_file:
- prod.env
depends_on:
- db
- backend
- redis
volumes:
static:
My Nginx configuration:
upstream api {
server backend:8000;
}
server {
listen 80;
location / {
proxy_pass http://api;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
location /static/ {
alias /usr/src/app/static/;
}
}
backend Dockerfile:
# syntax=docker/dockerfile:1
FROM python:3
WORKDIR /usr/src/app
RUN apt-get update
RUN apt-get install -y libgdal-dev gdal-bin netcat
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
COPY /django/requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY /django/django-entrypoint.sh /django-entrypoint.sh
RUN chmod +x /django-entrypoint.sh
COPY django /usr/src/app
ENTRYPOINT ["/django-entrypoint.sh"]
And the entrypoint:
#!/bin/sh
if [ "$POSTGRES_NAME" = "postgres" ]
then
echo "Waiting for Postgres..."
while ! nc -z $POSTGRES_HOST $POSTGRES_PORT; do
sleep 0.1
done
echo "PostgreSQL started"
fi
ls
# python manage.py flush --no-input
python manage.py migrate --no-input
python manage.py collectstatic --no-input
exec "$#"
In my files (local), I do not seem to see the '/static/' folder to be generated. How is this? I have check that static in backend and nginx by ssh in the container and the static folders were empty. In the logs, collectstatic was executed without an error with this message:
backend | 173 static files copied to '/static'.
You use a Docker named volume to hold the static files
volumes:
- static:/usr/src/app/static
# ^^^^^^
# a volume name, not a host path
This named volume only exists inside Docker's storage; you will not see its content on your host system or in your local source tree.
This isn't a problem for the setup you're describing here: since you're re-running collectstatic every time the container starts up, and the volume contents hide the image contents in this directory, there's no particular need for the files to exist in source control or your host filesystem. If you did need them, you could presumably run manage.py collectstatic in a non-Docker virtual environment.
Try by adding the following command in Dockerfile and re-build image.
RUN python manage.py collectstatic --noinput
You can place it after RUN pip install --no-cache-dir -r requirements.txt
This is the Dockerfile for my Django project:
FROM python:3.10.5-alpine
ENV PYTHONDONTWRITEBYTECODEBYDEFAULT=1
ENV PYTHONUNBUFFERED=1
RUN adduser --disabled-password appuser
USER appuser
WORKDIR /home/appuser/app
COPY requirements.txt .
USER root
RUN python -m pip install --no-cache-dir --disable-pip-version-check --requirement requirements.txt
USER appuser
COPY . .
ENTRYPOINT [ "./entrypoint.sh" ]
And Django settings regarding static assets:
STATIC_URL = 'static/'
STATIC_ROOT = BASE_DIR / 'static/'
And entrypoint.sh
#!/bin/sh
python manage.py makemigrations
python manage.py migrate
python manage.py collectstatic --no-input
gunicorn project.wsgi:application --bind=0.0.0.0:8000 --workers=4 --timeout=300 --log-level=debug --log-file=-
exec "$#"
When I start the container I shell into it and see that static folder is created and populated with admin staff.
However browsing http://127.0.0.1:8000/admin brings up the admin login page without any CSS and I get lots of 404 errors in the developer console.
I also changed STATIC_ROOT to /home/appuser/app/static/ and got the same.
Please assist.
Did you check for the permissions of the created static folder?
I had to manually change the permissions of the folders.
you could try with following Dockerfile for nginx:
FROM nginx:latest
RUN apt-get update && apt-get install -y procps
RUN mkdir -p /home/app/staticfiles
RUN chmod -R 755 /home/app/staticfiles
Could you try using this config.
Django:
STATIC_URL = "/static/"
STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")
STATICFILES_DIRS = (os.path.join(BASE_DIR, "static"),)
Dockerfile:
RUN mkdir -p /home/appuser/app/staticfiles
Nginx.conf
location /static/ {
alias /home/appuser/app/staticfiles/;
}
docker-compouse.yml something like:
web:
container_name: test_table_django
build: .
command:
sh -c "python manage.py collectstatic --no-input --clear &&
python manage.py migrate &&
gunicorn --workers=4 --bind=0.0.0.0:8000 test_table.wsgi:application"
volumes:
- .:/home/appuser/app
- static_volume:/home/appuser/app/staticfiles/
env_file:
- .env.prod
expose:
- 8000
depends_on:
- db
restart: always
nginx:
build: ./nginx
container_name: test_table_nginx
ports:
- 80:80
volumes:
- static_volume:/home/appuser/app/staticfiles/
The static URL should start with /.
You can also check the logs to see where it is trying to reach to.
BASE_DIR = Path(__file__).resolve().parent.parent.parent
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, '..', 'static')
This is probably the millionth django+nginx post, but since I didn't find an answer after more than 5 hours here it goes:
My issue is that not all static files get served, only some. The whole thing runs inside Docker where I run
RUN python manage.py collectstatic --noinput;
RUN python manage.py makemigrations;
RUN python manage.py migrate;
on each start, but it does not serve my new .js and .css files although they are in the same directories as the old ones.
I also see the message:
132 static files copied to '/static'.
and above that is the list of files being copied there, including the new ones.
Project Structure:
/djangoapp
/app
/static
/css
/js
/django
/Dockerfile
/docker-compose
settings.py:
DEBUG = False
STATIC_URL = '/static/'
STATIC_ROOT = '/static'
nginx.conf:
upstream web {
ip_hash;
server web:8000;
}
server {
location /static {
autoindex on;
alias /static;
}
location / {
proxy_connect_timeout 3600;
proxy_send_timeout 3600;
proxy_read_timeout 3600;
proxy_pass http://web/;
}
listen 8000;
server_name localhost;
}
Why aren't all static files being served?
EDIT:
Dockerfile:
FROM python:3.6.4-onbuild
RUN mkdir /config;
RUN mkdir /src;
COPY . /src
WORKDIR /src
RUN python manage.py collectstatic --noinput;
RUN python manage.py makemigrations;
RUN python manage.py migrate;
RUN chmod 775 -R /static
#this shows that the new files reside with the others in the same directory
RUN ls -R /static/
CMD gunicorn WebInterface.wsgi -b 0.0.0.0:8000 --timeout 3600
docker-compose.yml:
version : '3'
services:
web:
build: ./WebInterface
container_name: WebDocker
volumes:
- static-content:/static
expose:
- "80"
nginx:
image: nginx:1.12.2
container_name: NGINXDocker
ports:
- "8000:8000"
volumes:
- ./WebInterface:/src
- ./config/nginx:/etc/nginx/conf.d/
- static-content:/static
depends_on:
- web
volumes:
static-content:
Ok, with the additional info I think I know what's going on.
You run your python script to generate static files (which I assume it does) on build. On run, you mount the directory, so it will overwrite everything in the static directory.
Either don't mount it or add the scripts
python manage.py collectstatic --noinput;
python manage.py makemigrations;
python manage.py migrate;
in the entrypoint (https://docs.docker.com/engine/reference/builder/#entrypoint)
Also, the mounting of static into the nginx container doesn't do anything since you are only reverse proxying into the django container and not giving a root path. Or if it does work by some coincident, I'm not sure if it would get the newly generated files on startup.
Hope this helps, had a lot of fun with that stuff when I started with docker...
A workaround for now is to create the static folder on my local machine and then transfer the files to the desired position inside docker-compose.
When I find a real solution, on why collect static is not working within docker I will update this
Edit: Solution provided by LevinM
updated the Dockerfile (This only provides the image and installs python libraries from requirements.txt due to the 'onbuild' parameter):
FROM python:3.6.4-onbuild
updated docker-compose.yml:
version : '3'
services:
web:
build: ./WebInterface
entrypoint: bash -c "python manage.py collectstatic --noinput && python manage.py makemigrations && python manage.py migrate && gunicorn WebInterface.wsgi -b 0.0.0.0:8000 --timeout 3600";
container_name: WebDocker
volumes:
- ./WebInterface:/src
- static-content:/static
expose:
- "80"
nginx:
image: nginx:1.12.2
container_name: NGINXDocker
ports:
- "8000:8000"
volumes:
- ./WebInterface:/src
- ./config/nginx:/etc/nginx/conf.d/
- static-content:/static
depends_on:
- web
volumes:
static-content:
I'm having a situation while setting up Django and all the dependencies I need with Docker (docker-toolbox, docker-compose).
I'm encountering an error while I'm trying to access to my url http://192.168.99.100:8000/ which says 502 Bad Gateway (nginx/1.13.1). For this error I don't really understand from where it comes since it's the first time I'm using Django with nginx on Docker.
docker-compose.yml :
version: '2'
services:
nginx:
image: nginx:latest
container_name: nz01
ports:
- "8000:8000"
volumes:
- ./src:/src
- ./config/nginx:/etc/nginx/conf.d
- /static:/static
depends_on:
- web
web:
...
...
Dockerfile :
FROM python:latest
ENV PYTHONUNBUFFERED 1
#ENV C_FORCE_ROOT true
ENV APP_USER myapp
ENV APP_ROOT /src
RUN mkdir /src;
RUN groupadd -r ${APP_USER} \
&& useradd -r -m \
--home-dir ${APP_ROOT} \
-s /usr/sbin/nologin \
-g ${APP_USER} ${APP_USER}
WORKDIR ${APP_ROOT}
RUN mkdir /config
ADD config/requirements.pip /config/
RUN pip install -r /config/requirements.pip
USER ${APP_USER}
ADD . ${APP_ROOT}
config/nginx/... .conf
upstream web {
ip_hash;
server web:8000;
}
server {
location /static/ {
autoindex on;
alias /static/;
}
location / {
proxy_pass http://web/;
}
listen 8000;
server_name localhost;
}
Is there something I'm doing wrong ?
The issue here is with gunicorn command line argument, missing -b flag. It needs to be launched with -b flag for binding with the address specified. In your case gunicorn binds itself to default 127.0.0.1:8000 which isn't accessible to other containers. So, just change the command for web to following:
command: bash -c 'python manage.py makemigrations && python manage.py migrate && gunicorn oqtor.wsgi -b 0.0.0.0:8000'
That should make your web app accessible via nginx.
I am trying to run flask app server with uwsgi from supervisor and i getting error
[program:tmanalytics]
directory = /srv/www/tmapi/
command = uwsgi --socket /tmp/tmuwsgi.sock app:app --chmod-socket 777 --touch-reload /srv/www/tmapi/deployment.log
watch=/srv/www/tmapi/app/
stdout_logfile=/srv/www/tmapi/tmapi-analytics.log
autostart=true
autorestart=true
redirect_stderr=true
stopsignal=QUIT
try this
command = uwsgi -s /tmp/tmuwsgi.sock -w app:app --chmod-socket=666 --touch-reload /srv/www/tmapi/deployment.log