'django_1 | no port[s] to connect to' после запуска docker-compose up

Я новичок в docker, и написал контейнерное приложение django и приложение react. Когда я запускаю docker-compose up, я получаю странную, постоянную ошибку, что django не имеет порта(ов) для подключения. Запуск сервера со стороны react и python работает.

Frontend dockerfile:

COPY ./react_app/package.json .
RUN apk add --no-cache --virtual .gyp \
        python \
        make \
        g++ \
    && npm install \
    && apk del .gyp

COPY ./react_app .

ARG API_SERVER
ENV REACT_APP_API_SERVER=${API_SERVER}
RUN REACT_APP_API_SERVER=${API_SERVER} \ 
  npm run build

WORKDIR /usr/src/app
RUN npm install -g serve
COPY --from=builder /usr/src/app/build ./build
Django Python backend Dockerfile

WORKDIR /usr/src/app

ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

COPY ./requirements.txt .
RUN pip wheel --no-cache-dir --no-deps --wheel-dir /usr/src/app/wheels -r requirements.txt

FROM python:3.7.9-slim-stretch
RUN apt-get update && apt-get install -y --no-install-recommends netcat && \
   apt-get autoremove -y && \
   apt-get clean && \
   rm -rf /var/lib/apt/lists/*

COPY --from=builder /usr/src/app/wheels /wheels
COPY --from=builder /usr/src/app/requirements.txt .
RUN pip install --no-cache /wheels/*
WORKDIR /usr/src/app
COPY ./entrypoint.sh /usr/src/app/entrypoint.sh

COPY ./django_app .

RUN chmod +x /usr/src/app/entrypoint.sh
ENTRYPOINT ["/usr/src/app/entrypoint.sh"]
and the nginx dockerfile

FROM nginx:1.19.0-alpine

RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d

WORKDIR /usr/src/app

Django Python backend Dockerfile

WORKDIR /usr/src/app

ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

COPY ./requirements.txt .
RUN pip wheel --no-cache-dir --no-deps --wheel-dir /usr/src/app/wheels -r requirements.txt

FROM python:3.7.9-slim-stretch
RUN apt-get update && apt-get install -y --no-install-recommends netcat && \
   apt-get autoremove -y && \
   apt-get clean && \
   rm -rf /var/lib/apt/lists/*

COPY --from=builder /usr/src/app/wheels /wheels
COPY --from=builder /usr/src/app/requirements.txt .
RUN pip install --no-cache /wheels/*
WORKDIR /usr/src/app
COPY ./entrypoint.sh /usr/src/app/entrypoint.sh

COPY ./django_app .

RUN chmod +x /usr/src/app/entrypoint.sh
ENTRYPOINT ["/usr/src/app/entrypoint.sh"]
and the nginx dockerfile

FROM nginx:1.19.0-alpine

RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d

WORKDIR /usr/src/app

и докерфайл nginx

FROM nginx:1.19.10-alpine

RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d

WORKDIR /usr/src/app

Я не могу найти ничего связанного с этим, и я также новичок в Docker.

Это ошибка netcat. В частности, она возникает, когда вы указываете имя хоста, но не указываете порт при запуске nc.

Пример:

# nc -z 8.8.8.8
no port[s] to connect to

Затем ваш скрипт точки входа видит, что netcat завершился с ошибкой, и запускает его заново, пока не добьется успеха, чего никогда не произойдет.

Процесс отладки

Я подозревал, что это проблема с netcat, потому что сценарий точки входа выводит "Waiting for postgres...", но не "PostgreSQL started". Однако я не смог заставить netcat выдать ошибку "нет порта".

Поэтому я запустил копию базового образа и вручную установил netcat.

docker run -it python:3.7.9-slim-stretch bash
# in container
apt-get update
apt-get install netcat

Я все еще не мог заставить netcat выдать ошибку. Тогда я скачал исходный код netcat:

# still in container
apt-get source netcat

Затем, вооружившись копией исходного кода netcat, я нашел этот код:

  if (argv[optind] == NULL)
    bail ("no port[s] to connect to");

Перевод: Если код разбора аргументов, который только что закончил разбор значения хоста, исчерпал аргументы, то выдает ошибку "нет порта для подключения".

Мы можем проверить это, запустив nc внутри контейнера:

root@cc139fd40237:/source/netcat-1.10# nc -z localhost
no port[s] to connect to

Интересно, что Ubuntu имеет другую версию netcat, с другим сообщением об ошибке.

$ nc -z localhost
nc: missing port number

...так вот почему я не смог воспроизвести ошибку netcat вне контейнера!

Надежные сценарии оболочки

В этой строке либо DB_HOST, либо DB_PORT не установлены:

while ! nc -z $DB_HOST $DB_PORT; do

Помимо простого устранения проблемы, это хорошая возможность сделать ваш сценарий более надежным. Если бы вы добавили set -u в начало вашего сценария оболочки, то вместо этого вы получили бы гораздо более полезное сообщение об ошибке:

Waiting for postgres...
entrypoint.sh: 7: DB_PORT: parameter not set

Вы также можете использовать инструмент shellcheck - в вашем скрипте он рекомендует заключать аргументы в кавычки:

In entrypoint.sh line 6:
    while ! nc -z $DB_HOST $DB_PORT; do
                  ^------^ SC2086: Double quote to prevent globbing and word splitting.
                           ^------^ SC2086: Double quote to prevent globbing and word splitting.

Did you mean: 
    while ! nc -z "$DB_HOST" "$DB_PORT"; do

что также является отличной идеей.

Вернуться на верх