Контейнер Docker не использует последний файл composer.json - PullRequest
0 голосов
/ 05 июня 2019

Я схожу с ума здесь.

Я работал над файлами Dockerfile и docker-compose.yml для моего проекта. Я недавно обновил зависимости моего проекта. Когда я собираю проект вне контейнера, используя composer install, он строится с правильными зависимостями. Однако, когда я собираю проект в Docker-контейнере, он загружает и устанавливает последние зависимости, но затем каким-то образом запускает приложение, используя устаревшие зависимости!

Прежде всего, вот как выглядит мой Dockerfile:

FROM composer

# Set the working directory within the docker container
WORKDIR /app

# Copy in the app, then install dependencies.
COPY . /app
RUN composer install

Я исключил файл composer.lock и каталог vendor в моем .dockerignore:

vendor
composer.lock

Вот мой docker-compose.yml:

version: "3"
services:
  app:
    build: .
    volumes:
      - app:/app
  webserver:
    image: richarvey/nginx-php-fpm
    volumes:
      - app:/var/www/html

volumes:
  app:

Обратите внимание, что процесс сборки происходит внутри тома app. Я не думаю, что это должно быть частью проблемы, так как я запускаю docker system prune каждый раз, чтобы очистить все существующие тома.

Это то, что я делаю, чтобы запустить контейнер. Во время устранения неполадок я выполнял следующие команды для удаления любых кэшированных файлов перед запуском контейнера:

$ docker system prune
$ docker-compose build --no-cache
$ docker-compose up --force-recreate

Наблюдая за установкой и загрузкой зависимостей, Я вижу, что он загружает и устанавливает правильные версии! Так что в какой-то момент процесса он должен иметь правильный файл composer.json.

Тем не менее, как-то, как только сборка завершена и приложение запускается, я получаю те же старые предупреждения об устаревших зависимостях, и, конечно же, и composer.json внутри контейнера устарел!

Итак, мои вопросы:

  1. Как TF файл composer.json в контейнере устарел? ГДЕ откуда берется устаревший файл, так как он больше не существует ни в одном изображении или кэше ??
  2. Как TF удается установить последние зависимости с этим устаревшим файлом composer.json, но затем не использовать их, и фактически вернуть файл composer.json и зависимости ??

Ответы [ 2 ]

1 голос
/ 05 июня 2019

Мне кажется, проблема в том, что вы копируете свои локальные файлы в app-контейнер и запускаете composer install для этой копии.Поскольку это не повлияет на вашу хост-систему, ваш веб-сервер, который на самом деле будет обслуживать ваш проект, будет по-прежнему использовать устаревшую локальную версию вместо копии с другого вашего образа.

Вы можете попробовать использовать multi-stage builds или что-то вроде этого:

COPY FROM app:latest /app /var/www/html

Это скопирует артефакт из вашего "build-container", т.е. вашего проекта с установленной зависимостью в приложении, в реальный контейнер, в котором выполняетсякод, т.е. веб-сервер.К сожалению, я не думаю, что это будет работать (хорошо) с вашей настройкой, когда вы монтируете том в это место.

0 голосов
/ 06 июня 2019

Что ж, я наконец-то исправил эту проблему, хотя части моей первоначальной проблемы все еще смущают меня.

Вот что я узнал:

Процесс docker-compose up идет в следующем порядке:

  1. Если изображение уже существует, используйте его, даже если изменился Dockerfile (или используемые им файлы). (Этого можно избежать с помощью docker-compose up --build).
  2. Если изображение отсутствует, создайте его из Dockerfile.
  3. Смонтируйте тома, указанные в файле docker-compose.

Огромная часть моей проблемы заключалась в том, что я думал, что тома были смонтированы до процесса сборки, и что мое приложение будет установлено на этот том в результате выполнения следующих команд:

COPY . /app
RUN composer install

Однако эти файлы позже были перезаписаны, когда том был смонтирован в том же месте внутри контейнера (/app).

Теперь, поскольку я не монтировал каталог хоста, а просто эфемерный, именованный том, каталог /app должен был быть пустым. Я до сих пор не понимаю, почему это не так, учитывая, что я очищал свои существующие тома Docker с docker system prune перед каждой сборкой. Безотносительно.

В конце концов, я использовал решение @ dbrumann. Это было проще, не требовало использования каких-либо томов Docker и позволяло избежать наличия активного контейнера composer после завершения процесса сборки (это было бы плохо для производства). Мой Dockerfile теперь выглядит так:

Dockerfile

# Install dependencies using the composer image
FROM composer AS composer

# Set the working directory within the docker container
WORKDIR /app

# Copy in the app, then install dependencies.
COPY . .
RUN composer install

# Start the nginx server
FROM richarvey/nginx-php-fpm

# Copy over files from the composer image, which is then discarded automatically
WORKDIR /var/www/html
COPY --from=composer /app .

И новый docker-compose.yml:

version: "3.7"
services:
  webserver:
    build: .
    tty: true
    ports:
      - "80:80"
      - "443:443"
...