Как обновить код из Git в контейнер Docker
У меня есть файл Docker, пытающийся развернуть код Django в контейнер
FROM ubuntu:latest
MAINTAINER { myname }
#RUN echo "deb http://archive.ubuntu.com/ubuntu/ $(lsb_release -sc) main universe" >> /etc/apt/sou$
RUN apt-get update
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y tar git curl dialog wget net-tools nano buil$
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y python python-dev python-distribute python-p$
RUN mkdir /opt/app
WORKDIR /opt/app
#Pull Code
RUN git clone [email protected]/{user}/{repo}
RUN pip install -r website/requirements.txt
#EXPOSE = ["8000"]
CMD python website/manage.py runserver 0.0.0.0:8000
И затем я создаю свой код как docker build -t dockerhubaccount/demo:v1 .
, и это вытаскивает мой код из Bitbucket в контейнер. Я запускаю его как docker run -p 8000:8080 -td felixcheruiyot/demo:v1
, и все выглядит нормально.
Теперь я хочу обновить код, так как я использовал git clone ...
, у меня есть эта путаница:
- Как я могу обновить свой код, когда у меня появятся новые коммиты, а в контейнерах Docker его сборка поставляется с новым кодом (примечание: при запуске сборки он не извлекает его из-за кеша).
- Каков наилучший рабочий процесс для такого подхода?
Ответы
Ответ 1
Существует несколько подходов, которые вы можете использовать.
- Вы можете использовать
docker build --no-cache
, чтобы избежать использования кеша Git.
- Команда запуска вызывает
git pull
. Поэтому вместо запуска python manage.py
у вас есть что-то вроде CMD cd /repo && git pull && python manage.py
или используйте start script, если все сложнее.
Я предпочитаю 2. Вы также можете запустить задание cron для обновления кода в своем контейнере, но это немного больше работает и немного противоречит философии Docker.
Ответ 2
Я бы порекомендовал вам проверить код на вашем хосте и COPY
на изображении. Таким образом, он будет обновляться всякий раз, когда вы вносите изменения. Кроме того, во время разработки вы можете привязать исходный каталог к каталогу кода в контейнере, то есть любые изменения немедленно отражаются в контейнере.
Команда docker для репозиториев git, которая проверяет последнее обновление, была бы очень полезной, хотя!
Ответ 3
Другое решение.
Команда сборки Docker использует кеш, если строка инструкции точно такая же, как и в кешированном изображении. Итак, если вы пишете
RUN echo '2014122400' >/dev/null && git pull ...
В следующем обновлении вы измените следующее.
RUN echo '2014122501' >/dev/null && git pull ...
Это может предотвратить использование кеш-кером docker.
Ответ 4
Я хотел бы предложить другое возможное решение. Мне нужно предупредить, однако, что это определенно не "способ докеров" делать вещи и полагаться на существование томов (что может быть потенциальным блокировщиком в таких инструментах, как Docker Swarm и Kubernetes).
Основным принципом, который мы будем использовать, является тот факт, что содержимое каталогов контейнеров, которые используются в качестве тонов Докера, фактически хранится в файловой системе хоста. Ознакомьтесь с этой частью документации.
В вашем случае вы должны сделать /opt/app
Docker Volume. Вам не нужно явно указывать том в папку в файловой системе хоста, поскольку, как я опишу ниже, отображение можно получить динамически.
Итак, для стартеров оставьте свой файл Docker точно так, как он есть, и переключите команду создания контейнера на что-то вроде:
docker run -p 8000:8080 -v /opt/app --name some-name -td felixcheruiyot/demo:v1
Команда docker inspect -f {{index .Volumes "/opt/webapp"}} some-name
будет печатать полный путь файловой системы на хосте, где хранится ваш код (это, где я взял проверить трюк).
Вооружившись этим знанием, все, что вам нужно сделать, это заменить этот код и весь ваш набор.
Таким образом, очень простое развертывание script будет выглядеть примерно так:
code_path=$(docker inspect -f {{index .Volumes "/opt/webapp"}} some-name)
rm -rfv $code_path/*
cd $code_path
git clone [email protected]/{user}/{repo}
Преимущества, которые вы получаете с таким подходом:
- Не существует потенциально дорогостоящих отказов изображений без кекса.
- Нет необходимости переносить конкретную запущенную информацию приложения в команду run. Dockerfile является единственным источником необходимых для приложения приложений
UPDATE
Вы можете достичь тех же результатов, о которых я упомянул выше, используя docker cp (начиная с Docker 1.8). Таким образом, контейнер не должен иметь томов, и вы можете заменить код в контейнере так же, как и в файловой системе хоста.
Конечно, как я уже упоминал в начале ответа, это не "способ докеров" делать вещи, которые защищают контейнеры неизменными и воспроизводимыми.
Ответ 5
Если вы используете GitHub, вы можете использовать API GitHub, чтобы не кэшировать определенные команды RUN.
Для анализа JSON необходимо установить jq: apt-get install -y jq
Пример:
docker build --build-arg SHA=$(curl -s 'https://api.github.com/repos/Tencent/mars/commits' | jq -r '.[0].sha') -t imageName .
В файле Docker (команда ARG должна быть права перед RUN):
ARG SHA=LATEST
RUN SHA=${SHA} \
git clone https://github.com/Tencent/mars.git
Или если вы не хотите устанавливать jq:
SHA=$(curl -s 'https://api.github.com/repos/Tencent/mars/commits' | grep sha | head -1)
Если репозиторий имеет новые коммиты, будет выполнен git clone
.