Django容器并不完全在等待新的postgres容器

时间:2020-04-12 14:24:32

标签: python django postgresql docker docker-compose

好,所以,我正在尝试使用Django和docker启动一个项目。第一步很简单,我只想在容器中启动一个默认的django应用程序,然后在浏览器中看到django启动屏幕。我也想连接一个最简单的postgres容器来运行它。一切都很好。 我为我的应用创建了一个简单的图片,没什么花哨的:

FROM python:3.7
RUN mkdir /app
COPY requirements.txt /app/
WORKDIR /app
RUN pip install -r requirements.txt
COPY . /code/

还有一个docker-compose.yml:

version: '3'

services:
  python:
    build:
      context: .
      dockerfile: docker/python/Dockerfile
    volumes:
      - .:/app
    command: python manage.py runserver 0.0.0.0:8000
    ports:
      - "8000:8000"
    depends_on:
      - db
    restart: always
  db:
    image: postgres:9.5
    environment:
      POSTGRES_USER: cards
      POSTGRES_DB: cards
      POSTGRES_PASSWORD: cards

如您所见,我什至没有将任何源代码复制到docker映像中,我正在安装django的卷以从主机读取它。

问题是当我启动容器时,django服务器启动得太早而无法准备postgres,而psycopg2抛出了OperationalError。 这是我启动新容器时的日志:

Creating network "backend_default" with the default driver
Creating backend_db_1 ... done
Creating python       ... done
Attaching to backend_db_1, python
db_1      | The files belonging to this database system will be owned by user "postgres".
db_1      | This user must also own the server process.
db_1      |
db_1      | The database cluster will be initialized with locale "en_US.utf8".
db_1      | The default database encoding has accordingly been set to "UTF8".
db_1      | The default text search configuration will be set to "english".
db_1      |
db_1      | Data page checksums are disabled.
db_1      |
db_1      | fixing permissions on existing directory /var/lib/postgresql/data ... ok
db_1      | creating subdirectories ... ok
db_1      | selecting default max_connections ... 100
db_1      | selecting default shared_buffers ... 128MB
db_1      | selecting default timezone ... Etc/UTC
db_1      | selecting dynamic shared memory implementation ... posix
db_1      | creating configuration files ... ok
db_1      | creating template1 database in /var/lib/postgresql/data/base/1 ... ok
db_1      | initializing pg_authid ... ok
db_1      | setting password ... ok
db_1      | initializing dependencies ... ok
db_1      | creating system views ... ok
db_1      | loading system objects' descriptions ... ok
db_1      | creating collations ... ok
db_1      | creating conversions ... ok
db_1      | creating dictionaries ... ok
db_1      | setting privileges on built-in objects ... ok
db_1      | creating information schema ... ok
db_1      | loading PL/pgSQL server-side language ... ok
db_1      | vacuuming database template1 ... ok
db_1      | copying template1 to template0 ... ok
db_1      | copying template1 to postgres ... ok
python    | Watching for file changes with StatReloader
python    | Performing system checks...
python    |
db_1      | syncing data to disk ...
db_1      | WARNING: enabling "trust" authentication for local connections
db_1      | You can change this by editing pg_hba.conf or using the option -A, or
db_1      | --auth-local and --auth-host, the next time you run initdb.
db_1      | ok
db_1      |
db_1      | Success. You can now start the database server using:
db_1      |
db_1      |     pg_ctl -D /var/lib/postgresql/data -l logfile start
db_1      |
db_1      | waiting for server to start....LOG:  database system was shut down at 2020-04-12 14:17:12 UTC
db_1      | LOG:  MultiXact member wraparound protections are now enabled
db_1      | LOG:  database system is ready to accept connections
db_1      | LOG:  autovacuum launcher started
python    | System check identified no issues (0 silenced).
python    | Exception in thread django-main-thread:
python    | Traceback (most recent call last):
python    |   File "/usr/local/lib/python3.7/site-packages/django/db/backends/base/base.py", line 217, in ensure_connection
python    |     self.connect()
python    |   File "/usr/local/lib/python3.7/site-packages/django/db/backends/base/base.py", line 195, in connect
python    |     self.connection = self.get_new_connection(conn_params)
python    |   File "/usr/local/lib/python3.7/site-packages/django/db/backends/postgresql/base.py", line 178, in get_new_connection
python    |     connection = Database.connect(**conn_params)
python    |   File "/usr/local/lib/python3.7/site-packages/psycopg2/__init__.py", line 127, in connect
python    |     conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
python    | psycopg2.OperationalError: could not connect to server: Connection refused
python    |     Is the server running on host "db" (192.168.160.2) and accepting
python    |     TCP/IP connections on port 5432?
python    |
python    |
python    | The above exception was the direct cause of the following exception:
python    |
python    | Traceback (most recent call last):
python    |   File "/usr/local/lib/python3.7/threading.py", line 926, in _bootstrap_inner
python    |     self.run()
python    |   File "/usr/local/lib/python3.7/threading.py", line 870, in run
python    |     self._target(*self._args, **self._kwargs)
python    |   File "/usr/local/lib/python3.7/site-packages/django/utils/autoreload.py", line 54, in wrapper
python    |     fn(*args, **kwargs)
python    |   File "/usr/local/lib/python3.7/site-packages/django/core/management/commands/runserver.py", line 120, in inner_run
python    |     self.check_migrations()
python    |   File "/usr/local/lib/python3.7/site-packages/django/core/management/base.py", line 453, in check_migrations
python    |     executor = MigrationExecutor(connections[DEFAULT_DB_ALIAS])
python    |   File "/usr/local/lib/python3.7/site-packages/django/db/migrations/executor.py", line 18, in __init__
python    |     self.loader = MigrationLoader(self.connection)
python    |   File "/usr/local/lib/python3.7/site-packages/django/db/migrations/loader.py", line 49, in __init__
python    |     self.build_graph()
python    |   File "/usr/local/lib/python3.7/site-packages/django/db/migrations/loader.py", line 212, in build_graph
python    |     self.applied_migrations = recorder.applied_migrations()
python    |   File "/usr/local/lib/python3.7/site-packages/django/db/migrations/recorder.py", line 73, in applied_migrations
python    |     if self.has_table():
python    |   File "/usr/local/lib/python3.7/site-packages/django/db/migrations/recorder.py", line 56, in has_table
python    |     return self.Migration._meta.db_table in self.connection.introspection.table_names(self.connection.cursor())
python    |   File "/usr/local/lib/python3.7/site-packages/django/db/backends/base/base.py", line 256, in cursor
python    |     return self._cursor()
python    |   File "/usr/local/lib/python3.7/site-packages/django/db/backends/base/base.py", line 233, in _cursor
python    |     self.ensure_connection()
python    |   File "/usr/local/lib/python3.7/site-packages/django/db/backends/base/base.py", line 217, in ensure_connection
python    |     self.connect()
python    |   File "/usr/local/lib/python3.7/site-packages/django/db/utils.py", line 89, in __exit__
python    |     raise dj_exc_value.with_traceback(traceback) from exc_value
python    |   File "/usr/local/lib/python3.7/site-packages/django/db/backends/base/base.py", line 217, in ensure_connection
python    |     self.connect()
python    |   File "/usr/local/lib/python3.7/site-packages/django/db/backends/base/base.py", line 195, in connect
python    |     self.connection = self.get_new_connection(conn_params)
python    |   File "/usr/local/lib/python3.7/site-packages/django/db/backends/postgresql/base.py", line 178, in get_new_connection
python    |     connection = Database.connect(**conn_params)
python    |   File "/usr/local/lib/python3.7/site-packages/psycopg2/__init__.py", line 127, in connect
python    |     conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
python    | django.db.utils.OperationalError: could not connect to server: Connection refused
python    |     Is the server running on host "db" (192.168.160.2) and accepting
python    |     TCP/IP connections on port 5432?
python    |
python    |
db_1      |  done
db_1      | server started
db_1      | CREATE DATABASE
db_1      |
db_1      |
db_1      | /usr/local/bin/docker-entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*
db_1      |
db_1      | waiting for server to shut down...LOG:  received fast shutdown request
db_1      | LOG:  aborting any active transactions
db_1      | LOG:  autovacuum launcher shutting down
db_1      | .LOG:  shutting down
db_1      | LOG:  database system is shut down
db_1      |  done
db_1      | server stopped
db_1      |
db_1      | PostgreSQL init process complete; ready for start up.
db_1      |
db_1      | LOG:  database system was shut down at 2020-04-12 14:17:13 UTC
db_1      | LOG:  MultiXact member wraparound protections are now enabled
db_1      | LOG:  database system is ready to accept connections
db_1      | LOG:  autovacuum launcher started

如您所见,django容器在postgres设置的中间启动,并且无法连接。如果我只是重新启动django容器(另一件事,即使runserver命令失败,则docker容器也不会认为这是一个错误,并且无需重新启动就可以继续工作-我认为这是可以理解的,因为它是使用StatReloader启动的),当然可以,但是如果我可以让应用程序从第一次启动开始运行,而不是故意重新启动它,我将很高兴...

是否有防止发生这种情况的方法?我在这里犯了任何错误,还是应该对此采取其他方法?

谢谢。

1 个答案:

答案 0 :(得分:0)

您必须添加一些代码来检查数据库状态。

例如创建文件“ wait_for_db.sh”:

#!/bin/bash

echo "Waiting Postgres to launch on 5432..."

while ! nc -z db 5432; do   
    sleep 0.1 # wait for 1/10 of the second before check again
  done

  echo "Postgres launched"

然后将其添加到您的Dockerfile中:

COPY wait_for_db.sh .

并将docker-compose.yml中的命令更改为:

command: wait_for_db.sh && python manage.py runserver 0.0.0.0:8000

祝你好运