Как автоматически обновить контейнеры docker, если обновляются базовые изображения
скажем, у меня есть тривиальный контейнер, основанный на ubuntu:latest
. Теперь есть обновление для системы безопасности и ubuntu:latest
обновляется в репо docker .
Как я узнаю, что мой локальный образ и его контейнеры работают позади?
есть ли какая-то лучшая практика для автоматического обновления локальных образов и контейнеров, чтобы следовать обновлениям Docker repo, которые на практике дадут вам те же тонкости автоматического обновления, запущенного на a обычная ubuntu-машина
12 ответов:
один из способов сделать это-проехать через ваши системы CI/CD. После того, как ваш родительский образ построен, есть что-то, что сканирует ваши репозитории git для изображений с использованием этого родителя. Если он будет найден, вы отправите запрос на вытягивание, чтобы перейти к новым версиям изображения. Запрос на вытягивание, если все тесты пройдут, будет объединен, и у вас будет новый дочерний образ на основе обновленного родителя. Пример инструмента, который использует этот подход можно найти здесь: https://engineering.salesforce.com/open-sourcing-dockerfile-image-update-6400121c1a75 .
Если вы не контролируете свой родительский образ, как это было бы в случае, если вы зависите от официального
ubuntu
image, вы можете написать некоторые инструменты, которые обнаруживают изменения в теге родительского изображения и вызывают дочерние сборки изображений соответственно.
мы используем скрипт, который проверяет, запущен ли запущенный контейнер с последним изображением. Мы также используем сценарии инициализации upstart для запуска образа docker.
#!/usr/bin/env bash set -e BASE_IMAGE="registry" REGISTRY="registry.hub.docker.com" IMAGE="$REGISTRY/$BASE_IMAGE" CID=$(docker ps | grep $IMAGE | awk '{print }') docker pull $IMAGE for im in $CID do LATEST=`docker inspect --format "{{.Id}}" $IMAGE` RUNNING=`docker inspect --format "{{.Image}}" $im` NAME=`docker inspect --format '{{.Name}}' $im | sed "s/\///g"` echo "Latest:" $LATEST echo "Running:" $RUNNING if [ "$RUNNING" != "$LATEST" ];then echo "upgrading $NAME" stop docker-$NAME docker rm -f $NAME start docker-$NAME else echo "$NAME up to date" fi done
и инициализации выглядит так:
docker run -t -i --name $NAME $im /bin/bash
"докер путь" будет использовать докер-концентраторавтоматизированное построение. Элемент Ссылки На Репозиторий функция перестроит ваш контейнер, когда восходящий контейнер будет перестроен, и веб-перехватчиков функция отправит вам уведомление.
похоже, что веб-крючки ограничены вызовами HTTP POST. Вам нужно будет настроить службу, чтобы поймать их, или, возможно, использовать один из сообщений для почтовых служб там.
У меня нет заглянул в него, но новый Докер Универсальный Самолет Управления может иметь функцию для обнаружения обновленных контейнеров и повторного развертывания.
у меня была такая же проблема, и я думал, что ее можно просто решить с помощью вызова cron
unattended-upgrade
ежедневно.Я намерен использовать это как автоматическое и быстрое решение для обеспечения безопасности и обновления производственного контейнера, поскольку мне может потребоваться некоторое время для обновления моих образов и развертывания нового образа docker с последними обновлениями безопасности.
также можно автоматизировать построение и развертывание образа с помощью Github крючки
Я создал Docker-образ С этим автоматически проверяет и устанавливает обновления безопасности ежедневно (может работать непосредственно по
docker run itech/docker-unattended-upgrade
).Я также наткнулся на другой другой подход чтобы проверить, нуждается ли контейнер в обновлении.
Моя полная реализация:
Dockerfile
FROM ubuntu:14.04 RUN apt-get update \ && apt-get install -y supervisor unattended-upgrades \ && rm -rf /var/lib/apt/lists/* COPY install /install RUN chmod 755 install RUN /install COPY start /start RUN chmod 755 /start
помощник скрипты
установить
#!/bin/bash set -e cat > /etc/supervisor/conf.d/cron.conf <<EOF [program:cron] priority=20 directory=/tmp command=/usr/sbin/cron -f user=root autostart=true autorestart=true stdout_logfile=/var/log/supervisor/%(program_name)s.log stderr_logfile=/var/log/supervisor/%(program_name)s.log EOF rm -rf /var/lib/apt/lists/* ENTRYPOINT ["/start"]
старт
#!/bin/bash set -e echo "Adding crontab for unattended-upgrade ..." echo "0 0 * * * root /usr/bin/unattended-upgrade" >> /etc/crontab # can also use @daily syntax or use /etc/cron.daily echo "Starting supervisord ..." exec /usr/bin/supervisord -n -c /etc/supervisor/supervisord.conf
Edit
Я разработал небольшой инструмент docker-run который работает как контейнер docker и может использоваться для обновления пакетов внутри всех или выбранных запущенных контейнеров, он также может использоваться для запуска любых произвольных команд.
смогите легко быть испытано с следующим команда:
docker run --rm -v /var/run/docker.sock:/tmp/docker.sock itech/docker-run exec
, который по умолчанию будет выполнять
date
команда во всех запущенных контейнерах и отображение результатов. Если вы пройдетеupdate
вместоexec
он будет выполнятьapt-get update
следовал поapt-get upgrade -y
во всех запущенных контейнеров
можно использовать башня чтобы следить за обновлениями образа, из которого создается экземпляр контейнера, автоматически извлеките обновление и перезапустите контейнер с помощью обновленного образа. Однако это не решает проблему восстановления ваших собственных пользовательских изображений, когда есть изменение в исходном изображении, на котором оно основано. Вы можете рассматривать это как проблему из двух частей: (1) зная, когда восходящее изображение было обновлено, и (2) делая фактическое перестроение изображения. (1) может быть решена достаточно легко, но (2) во многом зависит от вашей локальной среды сборки/практики, поэтому, вероятно, гораздо сложнее создать обобщенное решение для этого.
Если вы можете использовать Docker Hub в автоматизированное построение, вся проблема может быть решена относительно чисто с помощью ссылки на репозиторий функция, которая позволяет автоматически запускать перестройку при обновлении связанного репозитория (возможно, вышестоящего). Вы также можете настроить webhook to уведомляет вас, когда происходит автоматическая сборка. Если вы хотите уведомление по электронной почте или SMS, вы можете подключить webhook к IFTTT Maker. Я нашел частичное будильника пользовательского интерфейса, чтобы быть немного запутанным, но вы настроить настройки веб-перехватчик на должность https://maker.ifttt.com/trigger/
docker_xyz_image_built
/С/ключ/your_key
.Если вам нужно построить локально, вы можете по крайней мере решить проблему получения уведомлений при обновлении восходящего изображения, создав манекен РЕПО в Docker Hub связано с интересующими вас РЕПО. Единственной целью фиктивного РЕПО было бы вызвать webhook, когда он будет перестроен (что подразумевает, что один из его связанных РЕПО был обновлен). Если вы можете получить этот веб-крючок, вы можете даже использовать его, чтобы вызвать перестройку на вашей стороне.
вы не знаете ваш контейнер не работает докер тянуть. Тогда вам нужно будет восстановить или композицию ваш образ.
docker pull image:tag docker-compose -f docker-compose.yml -f production.yml up -d --build
команды могут быть помещены в сценарий вместе с чем-либо еще, необходимым для завершения обновления, хотя надлежащий контейнер не будет нуждаться в чем-либо дополнительном.
Я не буду вдаваться в весь вопрос о том, хотите ли вы автоматические обновления в производстве (я думаю, что нет). Я просто оставляю это здесь для справки, если кто-нибудь сочтет это полезным. Обновите все изображения docker до последней версии с помощью следующей команды в терминале:
# docker images | awk '(NR>1) && (!~/none/) {print ":"}' | xargs -L1 docker pull
другой подход может заключаться в том, чтобы предположить, что ваш базовый образ довольно быстро отстает (и это очень вероятно), и периодически принудительно создавать другой образ вашего приложения (например, каждую неделю), а затем повторно развертывать его, если он изменился.
насколько я могу судить, популярные базовые образы, такие как официальный Debian или Java, обновляют свои теги для удовлетворения исправлений безопасности, поэтому теги не являются неизменяемыми (если вы хотите более сильную гарантию того, что вам нужно использовать ссылку [image:@digest], доступно в более поздних версиях Docker). Поэтому, если вы должны были построить свой образ с
docker build --pull
, то ваше приложение должно получить последнюю и самую большую из базового тега изображения, на который вы ссылаетесь.поскольку изменяемые теги могут сбивать с толку, лучше каждый раз увеличивать номер версии вашего приложения, чтобы по крайней мере на вашей стороне все было чище.
поэтому я не уверен, что сценарий, предложенный в одной из предыдущих ответов выполняет задание, так как он не перестраивает образ приложения - он просто обновляет тег базового образа, а затем перезапускает контейнер, но новый контейнер по-прежнему ссылается на старый хэш базового образа.
Я бы не выступал за запуск заданий типа cron в контейнерах (или любых других процессах, если это действительно необходимо), поскольку это противоречит мантре запуска только одного процесса на контейнер (есть различные аргументы о том, почему это лучше, поэтому я не буду вдаваться в это здесь.)
предпосылка к моему ответу:
- контейнеры запускаются с тегами.
- тот же тег можно указать на другой UUID изображения, как нам нравится/ чувствовать себя уместно.
- обновления, выполненные для изображения, могут быть зафиксированы в новом слое изображения
подход
- построить все контейнеры в первую очередь с помощью сценария обновления security-patch
- построить автоматизированный процесс для следующий
- запустите существующий образ в новый контейнер с помощью сценария исправления безопасности в качестве команды
- зафиксировать изменения в изображении как
- существующий тег - > с последующим перезапуском контейнеров один за другим
- новая версия тега - > заменить несколько контейнеров с новым тегом - > проверить - > переместить все контейнеры в новый тег
дополнительно, низкопробное изображение можно модернизировать / контейнер с полным новое базовое изображение может быть построено через регулярные промежутки времени, так как сопровождающий чувствует себя необходимым
преимущества
- мы сохраняем старую версию образа при создании нового исправленного образа безопасности, поэтому при необходимости мы можем откатиться к предыдущему запущенному образу
- мы сохраняем кэш docker, следовательно, меньше сетевой передачи (только измененный слой попадает на провод)
- процесс обновления можно проверить в промежуточном прежде чем перейти к прод
- Это может быть контролируемый процесс, поэтому патчи безопасности только тогда, когда это необходимо/ считается важным, могут быть выдвинуты.
управление зависимостями для докеров изображений является реальной проблемой. Я часть команды, которая построила инструмент, MicroBadger, чтобы помочь с этим путем мониторинга изображений контейнеров и проверки метаданных. Одна из его особенностей заключается в том, чтобы вы могли настроить уведомление webhook, которое вызывается при изменении интересующего вас изображения (например, базового изображения).
есть много ответов, но ни один из них не отвечал моим потребностям. Я хотел получить реальный ответ на вопрос № 1 спрашивающего. Как узнать, когда изображение обновляется hub.docker.com?
ниже скрипт может быть запущен ежедневно. При первом запуске он получает базовую версию тегов и даты обновления из реестра концентратора и сохраняет их локально. С тех пор, каждый раз, когда он запускается, он проверяет реестр на наличие новых тегов и обновление даты. Поскольку это изменяется каждый раз, когда существует новое изображение, оно сообщает мы, если базовый образ изменился. Вот этот скрипт:
#!/bin/bash DATAPATH='/data/docker/updater/data' if [ ! -d "${DATAPATH}" ]; then mkdir "${DATAPATH}"; fi IMAGES=$(docker ps --format "{{.Image}}") for IMAGE in $IMAGES; do ORIGIMAGE=${IMAGE} if [[ "$IMAGE" != *\/* ]]; then IMAGE=library/${IMAGE} fi IMAGE=${IMAGE%%:*} echo "Checking ${IMAGE}" PARSED=${IMAGE//\//.} if [ ! -f "${DATAPATH}/${PARSED}" ]; then # File doesn't exist yet, make baseline echo "Setting baseline for ${IMAGE}" curl -s "https://registry.hub.docker.com/v2/repositories/${IMAGE}/tags/" > "${DATAPATH}/${PARSED}" else # File does exist, do a compare NEW=$(curl -s "https://registry.hub.docker.com/v2/repositories/${IMAGE}/tags/") OLD=$(cat "${DATAPATH}/${PARSED}") if [[ "${VAR1}" == "${VAR2}" ]]; then echo "Image ${IMAGE} is up to date"; else echo ${NEW} > "${DATAPATH}/${PARSED}" echo "Image ${IMAGE} needs to be updated"; H=`hostname` ssh -i /data/keys/<KEYFILE> <USER>@<REMOTEHOST>.com "{ echo \"MAIL FROM: root@${H}\"; echo \"RCPT TO: <USER>@<EMAILHOST>.com\"; echo \"DATA\"; echo \"Subject: ${H} - ${IMAGE} needs update\"; echo \"\"; echo -e \"\n${IMAGE} needs update.\n\ndocker pull ${ORIGIMAGE}\"; echo \"\"; echo \".\"; echo \"quit\"; sleep 1; } | telnet <SMTPHOST> 25" fi fi done;
вы хотите изменить
DATAPATH
переменной в верхней части, и изменить команду уведомлений по электронной почте в конце, чтобы удовлетворить ваши потребности. Для меня у меня есть SSH на сервере в другой сети, где находится мой SMTP. Но вы можете легко использовать тоже.теперь, вы также хотите, чтобы проверить наличие обновленных пакетов внутри самих контейнеров. Это на самом деле, вероятно, более эффективно, чем делать "потяните", как только ваши контейнеры работают. Вот сценарий, чтобы снять это:
#!/bin/bash function needsUpdates() { RESULT=$(docker exec bash -c ' \ if [[ -f /etc/apt/sources.list ]]; then \ grep security /etc/apt/sources.list > /tmp/security.list; \ apt-get update > /dev/null; \ apt-get upgrade -oDir::Etc::Sourcelist=/tmp/security.list -s; \ fi; \ ') RESULT=$(echo $RESULT) GOODRESULT="Reading package lists... Building dependency tree... Reading state information... Calculating upgrade... 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded." if [[ "${RESULT}" != "" ]] && [[ "${RESULT}" != "${GOODRESULT}" ]]; then return 0 else return 1 fi } function sendEmail() { echo "Container needs security updates"; H=`hostname` ssh -i /data/keys/<KEYFILE> <USRER>@<REMOTEHOST>.com "{ echo \"MAIL FROM: root@${H}\"; echo \"RCPT TO: <USER>@<EMAILHOST>.com\"; echo \"DATA\"; echo \"Subject: ${H} - container needs security update\"; echo \"\"; echo -e \"\n container needs update.\n\n\"; echo -e \"docker exec bash -c 'grep security /etc/apt/sources.list > /tmp/security.list; apt-get update > /dev/null; apt-get upgrade -oDir::Etc::Sourcelist=/tmp/security.list -s'\n\n\"; echo \"Remove the -s to run the update\"; echo \"\"; echo \".\"; echo \"quit\"; sleep 1; } | telnet <SMTPHOST> 25" } CONTAINERS=$(docker ps --format "{{.Names}}") for CONTAINER in $CONTAINERS; do echo "Checking ${CONTAINER}" if needsUpdates $CONTAINER; then sendEmail $CONTAINER fi done
выше ответы также правильные
есть два подхода
- использовать webhooks
- запустить скрипт для каждой конкретной минуты, чтобы получить свежий тянуть докер изображений
Я просто разделяю скрипт может быть это будет полезно для вас! Вы можете использовать его с cronjob, я пытался успешно на OSX
#!/bin/bash ##You can use below commented line for setting cron tab for running cron job and to store its O/P in one .txt file #* * * * * /usr/bin/sudo -u admin -i bash -c /Users/Swapnil/Documents/checkimg.sh > /Users/Swapnil/Documents/cron_output.log 2>&1 # Example for the Docker Hub V2 API # Returns all images and tags associated with a Docker Hub organization account. # Requires 'jq': https://stedolan.github.io/jq/ # set username, password, and organization # Filepath where your docker-compose file is present FILEPATH="/Users/Swapnil/Documents/lamp-alpine" # Your Docker hub user name UNAME="ur username" # Your Docker hub user password UPASS="ur pwd" # e.g organisation_name/image_name:image_tag ORG="ur org name" IMGNAME="ur img name" IMGTAG="ur img tag" # Container name CONTNAME="ur container name" # Expected built mins BUILDMINS="5" #Generally cronjob frequency CHECKTIME="5" NETWORKNAME="${IMGNAME}_private-network" #After Image pulling, need to bring up all docker services? DO_DOCKER_COMPOSE_UP=true # ------- echo "Eecuting Script @ date and time in YmdHMS: $(date +%Y%m%d%H%M%S)" set -e PIDFILE=/Users/Swapnil/Documents/$IMGNAME/forever.pid if [ -f $PIDFILE ] then PID=$(cat $PIDFILE) ps -p $PID > /dev/null 2>&1 if [ $? -eq 0 ] then echo "Process already running" exit 1 else ## Process not found assume not running echo $$ echo $$ > $PIDFILE if [ $? -ne 0 ] then echo "Could not create PID file" exit 1 fi fi else echo $$ > $PIDFILE if [ $? -ne 0 ] then echo "Could not create PID file" exit 1 fi fi # Check Docker is running or not; If not runing then exit if docker info|grep Containers ; then echo "Docker is running" else echo "Docker is not running" rm $PIDFILE exit 1 fi # Check Container is running or not; and set variable CONT_INFO=$(docker ps -f "name=$CONTNAME" --format "{{.Names}}") if [ "$CONT_INFO" = "$CONTNAME" ]; then echo "Container is running" IS_CONTAINER_RUNNING=true else echo "Container is not running" IS_CONTAINER_RUNNING=false fi # get token echo "Retrieving token ..." TOKEN=$(curl -s -H "Content-Type: application/json" -X POST -d '{"username": "'${UNAME}'", "password": "'${UPASS}'"}' https://hub.docker.com/v2/users/login/ | jq -r .token) # get list of repositories echo "Retrieving repository list ..." REPO_LIST=$(curl -s -H "Authorization: JWT ${TOKEN}" https://hub.docker.com/v2/repositories/${ORG}/?page_size=100 | jq -r '.results|.[]|.name') # output images & tags echo "Images and tags for organization: ${ORG}" echo for i in ${REPO_LIST} do echo "${i}:" # tags IMAGE_TAGS=$(curl -s -H "Authorization: JWT ${TOKEN}" https://hub.docker.com/v2/repositories/${ORG}/${i}/tags/?page_size=100 | jq -r '.results|.[]|.name') for j in ${IMAGE_TAGS} do echo " - ${j}" done #echo done # Check Perticular image is the latest or not #imm=$(curl -s -H "Authorization: JWT ${TOKEN}" https://hub.docker.com/v2/repositories/${ORG}/${IMGNAME}/tags/?page_size=100) echo "-----------------" echo "Last built date details about Image ${IMGNAME} : ${IMGTAG} for organization: ${ORG}" IMAGE_UPDATED_DATE=$(curl -s -H "Authorization: JWT ${TOKEN}" https://hub.docker.com/v2/repositories/${ORG}/${IMGNAME}/tags/?page_size=100 | jq -r '.results|.[]|select(.name | contains("'${IMGTAG}'")).last_updated') echo "On Docker Hub IMAGE_UPDATED_DATE---$IMAGE_UPDATED_DATE" echo "-----------------" IMAGE_CREATED_DATE=$(docker image inspect ${ORG}/${IMGNAME}:${IMGTAG} | jq -r '.[]|.Created') echo "Locally IMAGE_CREATED_DATE---$IMAGE_CREATED_DATE" updatedDate=$(date -jf '%Y-%m-%dT%H:%M' "${IMAGE_UPDATED_DATE:0:16}" +%Y%m%d%H%M%S) createdDate=$(date -jf '%Y-%m-%dT%H:%M' "${IMAGE_CREATED_DATE:0:16}" +%Y%m%d%H%M%S) currentDate=$(date +%Y%m%d%H%M%S) start_date=$(date -jf "%Y%m%d%H%M%S" "$currentDate" "+%s") end_date=$(date -jf "%Y%m%d%H%M%S" "$updatedDate" "+%s") updiffMins=$(( ($start_date - $end_date) / (60) )) if [[ "$updiffMins" -lt $(($CHECKTIME+1)) ]]; then if [ ! -d "${FILEPATH}" ]; then mkdir "${FILEPATH}"; fi cd "${FILEPATH}" pwd echo "updatedDate---$updatedDate" > "ScriptOutput_${currentDate}.txt" echo "createdDate---$createdDate" >> "ScriptOutput_${currentDate}.txt" echo "currentDate---$currentDate" >> "ScriptOutput_${currentDate}.txt" echo "Found after regular checking time -> Docker hub's latest updated image is new; Diff ${updiffMins} mins" >> "ScriptOutput_${currentDate}.txt" echo "Script is checking for latest updates after every ${CHECKTIME} mins" >> "ScriptOutput_${currentDate}.txt" echo "Fetching all new" echo "---------------------------" if $IS_CONTAINER_RUNNING ; then echo "Container is running" else docker-compose down echo "Container stopped and removed; Network removed" >> "ScriptOutput_${currentDate}.txt" fi echo "Image_Created_Date=$currentDate" > ".env" echo "ORG=$ORG" >> ".env" echo "IMGNAME=$IMGNAME" >> ".env" echo "IMGTAG=$IMGTAG" >> ".env" echo "CONTNAME=$CONTNAME" >> ".env" echo "NETWORKNAME=$NETWORKNAME" >> ".env" docker-compose build --no-cache echo "Docker Compose built" >> "ScriptOutput_${currentDate}.txt" if $DO_DOCKER_COMPOSE_UP ; then docker-compose up -d echo "Docker services are up now, checked in" >> "ScriptOutput_${currentDate}.txt" else echo "Docker services are down, checked in" >> "ScriptOutput_${currentDate}.txt" fi elif [[ "$updatedDate" -gt "$createdDate" ]]; then echo "Updated is latest" start_date=$(date -jf "%Y%m%d%H%M%S" "$updatedDate" "+%s") end_date=$(date -jf "%Y%m%d%H%M%S" "$createdDate" "+%s") diffMins=$(( ($start_date - $end_date) / (60) )) if [[ "$BUILDMINS" -lt "$diffMins" ]]; then if [ ! -d "${FILEPATH}" ]; then mkdir "${FILEPATH}"; fi cd "${FILEPATH}" pwd echo "updatedDate---$updatedDate" > "ScriptOutput_${currentDate}.txt" echo "createdDate---$createdDate" >> "ScriptOutput_${currentDate}.txt" echo "currentDate---$currentDate" >> "ScriptOutput_${currentDate}.txt" echo "Found after comparing times -> Docker hub's latest updated image is new; Diff ${diffMins} mins" >> "ScriptOutput_${currentDate}.txt" echo "Actual image built time is less i.e. ${diffMins} mins than MAX expexted BUILD TIME i.e. ${BUILDMINS} mins" >> "ScriptOutput_${currentDate}.txt" echo "Fetching all new" >> "ScriptOutput_${currentDate}.txt" echo "-----------------------------" if $IS_CONTAINER_RUNNING ; then echo "Container is running" else docker-compose down echo "Container stopped and removed; Network removed" >> "ScriptOutput_${currentDate}.txt" fi echo "Image_Created_Date=$currentDate" > ".env" echo "ORG=$ORG" >> ".env" echo "IMGNAME=$IMGNAME" >> ".env" echo "IMGTAG=$IMGTAG" >> ".env" echo "CONTNAME=$CONTNAME" >> ".env" echo "NETWORKNAME=$NETWORKNAME" >> ".env" docker-compose build --no-cache echo "Docker Compose built" >> "ScriptOutput_${currentDate}.txt" if $DO_DOCKER_COMPOSE_UP ; then docker-compose up -d echo "Docker services are up now" >> "ScriptOutput_${currentDate}.txt" else echo "Docker services are down" >> "ScriptOutput_${currentDate}.txt" fi elif [[ "$BUILDMINS" -gt "$diffMins" ]]; then echo "Docker hub's latest updated image is NOT new; Diff ${diffMins} mins" echo "Docker images not fetched" else echo "Docker hub's latest updated image is NOT new; Diff ${diffMins} mins" echo "Docker images not fetched" fi elif [[ "$createdDate" -gt "$updatedDate" ]]; then echo "Created is latest" start_date=$(date -jf "%Y%m%d%H%M%S" "$createdDate" "+%s") end_date=$(date -jf "%Y%m%d%H%M%S" "$updatedDate" "+%s") echo "Docker hub has older docker image than local; Older than $(( ($start_date - $end_date) / (60) ))mins" fi echo echo "------------end---------------" rm $PIDFILE
вот мой docker-compose file
version: "3.2" services: lamp-alpine: build: context: . container_name: "${CONTNAME}" image: "${ORG}/${IMGNAME}:${IMGTAG}" ports: - "127.0.0.1:80:80" networks: - private-network networks: private-network: driver: bridge