이미지가 변경된 후 도커 컨테이너를 업그레이드하는 방법


518

공식 mysql : 5.6.21 image를 가져 왔다고 가정 해 봅시다 .

여러 도커 컨테이너를 만들어이 이미지를 배포했습니다.

이 컨테이너는 MySQL 5.6.22가 출시 될 때까지 얼마 동안 실행되었습니다. mysql : 5.6의 공식 이미지는 새로운 릴리스로 업데이트되지만 컨테이너는 여전히 5.6.21로 실행됩니다.

이미지의 변경 사항 (예 : MySQL 배포판 업그레이드)을 기존의 모든 컨테이너에 전파하려면 어떻게해야합니까? 이 작업을 수행하는 올바른 Docker 방법은 무엇입니까?

답변:


578

답변을 평가하고 주제를 연구 한 후 요약하고 싶습니다.

컨테이너를 업그레이드하는 Docker 방법은 다음과 같습니다.

응용 프로그램 컨테이너는 응용 프로그램 데이터를 저장해서는 안됩니다 . 이렇게하면 언제든지 다음과 같은 것을 실행하여 앱 컨테이너를 최신 버전으로 바꿀 수 있습니다.

docker pull mysql
docker stop my-mysql-container
docker rm my-mysql-container
docker run --name=my-mysql-container --restart=always \
  -e MYSQL_ROOT_PASSWORD=mypwd -v /my/data/dir:/var/lib/mysql -d mysql

호스트 (볼륨으로 마운트 된 디렉토리) 또는 특수 데이터 전용 컨테이너 에 데이터를 저장할 수 있습니다 . 그것에 대해 더 읽어보기

컨테이너 내에서 업그레이드 응용 프로그램 (예 : yum / apt-get 업그레이드)은 안티 패턴으로 간주됩니다 . 응용 프로그램 컨테이너는 변경 불가능 하며, 재현 가능한 동작을 보장해야합니다. 일부 공식 응용 프로그램 이미지 (특히 mysql : 5.6)는 자체 업데이트하도록 설계되지 않았습니다 (apt-get 업그레이드가 작동하지 않음).

답변을 주신 모든 분들께 감사 드리고 싶습니다. 그래서 우리는 모든 다른 접근법을 볼 수있었습니다.


31
데이터 마이그레이션이 필요한 경우 어떻게합니까? 새 서버는 이전 형식이므로 데이터를 마운트 할 수 없습니다. 마이그레이션이 진행 중임을 알고 데이터 표현을 변경해야합니다.
Dor Rotman

12
이미지 디자이너는이를 설명하고 컨테이너를 처음 실행할 때 사용자 지정 (예 : 데이터 마이그레이션) 명령을 실행할 수 있어야한다고 생각합니다.
Yaroslav Stavnichiy 2016 년


4
@static_rtti docker rename my-mysql-container trash-container새로운 것을 만들기 전에는 어떻습니까?
Franklin Yu

4
컨테이너를 수동으로 중지, 제거 및 다시 만들 필요없이 컨테이너를 업데이트하는 올인원 명령이 있습니까?
Michaël Perrin

83

볼륨을 호스트 디렉토리에 대한 링크로 마운트하는 것을 좋아하지 않으므로 완전히 docker 관리 컨테이너로 docker 컨테이너를 업그레이드하기위한 패턴을 생각해 냈습니다. 새 도커 컨테이너를 만들면 --volumes-from <container>업데이트 된 이미지가있는 새 컨테이너에 도커 관리 볼륨의 소유권이 공유됩니다.

docker pull mysql
docker create --volumes-from my_mysql_container [...] --name my_mysql_container_tmp mysql

원본을 my_mysql_container아직 즉시 제거 하지 않으면 업그레이드 된 컨테이너에 올바른 데이터가 없거나 위생 테스트에 실패한 경우 알려진 작업 컨테이너로 되돌릴 수 있습니다.

이 시점에서 나는 보통 컨테이너가 가지고있는 백업 스크립트를 실행하여 문제가 생길 경우에 대비하여 안전망을 제공합니다.

docker stop my_mysql_container
docker start my_mysql_container_tmp

이제 새 컨테이너에있을 것으로 예상되는 데이터가 있는지 확인하고 상태 확인을 실행할 수 있습니다.

docker rm my_mysql_container
docker rename my_mysql_container_tmp my_mysql_container

컨테이너가 컨테이너를 사용하는 동안 도커 볼륨이 달라 붙어 원래 컨테이너를 안전하게 삭제할 수 있습니다. 원래 컨테이너가 제거되면 새 컨테이너는 원래 이름을 그대로 사용하여 모든 것을 처음부터 예쁘게 만들 수 있습니다.

도커 컨테이너를 업그레이드하기 위해이 패턴을 사용하면 두 가지 주요 이점이 있습니다. 첫째, 볼륨을 업그레이드 된 컨테이너로 직접 전송할 수 있도록하여 호스트를 호스트에 볼륨을 마운트 할 필요가 없습니다. 두 번째로, 도커 컨테이너가 작동하지 않는 위치에 있지 않습니다. 따라서 업그레이드에 실패하면 원래 도커 컨테이너를 다시 회전시켜 이전의 작동 방식으로 쉽게 되돌릴 수 있습니다.


3
Docker 컨테이너 내부에 호스트 볼륨을 마운트하는 것이 좋지 않은 이유는 무엇입니까? 나는 한 장착 예 : - (나는 내가 그 일에 대해 인수에 관심 그래서 정확하게하고있어)가 ./postgres-data/:/var/lib/postgres/data- 즉, 호스트 디렉토리 마운트 ./postgres-data/내 PostgreSQL의 컨테이너 내부).
KajMagnus

4
@KajMagnus 나는 docker swarms를 많이 사용하며 swarm에서 잘 작동하도록 컨테이너를 작성하고 싶습니다. swarm에서 컨테이너를 스핀 업 할 때 컨테이너가 어떤 swarm 노드에 있는지 알지 못하므로 원하는 데이터가 포함 된 호스트 경로를 신뢰할 수 없습니다. Docker 1.9 (i think) 볼륨을 호스트간에 공유 할 수 있기 때문에 설명 된 방법을 사용하여 컨테이너를 업그레이드 및 마이그레이션하는 것이 쉬워집니다. 대안은 일부 네트워크 볼륨이 모든 웜 노드에 마운트되도록하는 것이지만 유지 관리에 큰 어려움이있는 것 같습니다.
kMaiSmith

감사! 좋아, 이제 호스트 볼륨을 마운트하는 것도 피하고 싶은 것처럼 보입니다. 내 앱이 인기를
얻었고

32

더 일반적인 (mysql에 국한되지 않은) 답변을 제공하기 위해 ...

  1. 한마디로

서비스 이미지 레지스트리 ( https://docs.docker.com/compose/compose-file/#image ) 와 동기화 하십시오 .

docker-compose pull 

docker-compose 파일 또는 이미지가 변경된 경우 컨테이너를 다시 만듭니다.

docker-compose up -d
  1. 배경

컨테이너 이미지 관리는 docker-compose를 사용하는 이유 중 하나입니다 ( https://docs.docker.com/compose/reference/up/ 참조 )

서비스에 대한 기존 컨테이너가 있고 컨테이너 작성 후 서비스 구성 또는 이미지가 변경된 경우, docker-compose up은 컨테이너를 중지하고 다시 작성하여 마운트 된 볼륨을 보존하여 변경 사항을 선택합니다. 작성이 변경 사항을 선택하지 못하게하려면 --no-recreate 플래그를 사용하십시오.

마운트 된 외부 "볼륨"( https://docs.docker.com/compose/compose-file/#volumes 참조 ) 또는 데이터 컨테이너를 통해 docker-compose가 데이터 관리 측면을 다루고 있습니다.

이것은 이전 버전과의 호환성 및 데이터 마이그레이션 문제를 건드리지 않지만 Docker가 아닌 "응용 적"문제이며 릴리스 정보 및 테스트와 비교하여 확인해야합니다


버전 관리를 어떻게 수행합니까? 예를 들어 새 이미지는 foo / image : 2이고 docker-compose.yml에는 이미지 : foo / image : 1?
dman

감사합니다. 최고의 답변!
Mick

이것이 확실한 방법이지만 컨테이너를 다시 만들면 컨테이너의 변경 사항이 계속 손실된다는 것을 알아야합니다. 따라서 마운트 된 볼륨 내에서만 컨테이너 변경을 유지해야합니다.
Petr Bodnár

23

이 프로세스를 자동으로 수행하려면 (@Yaroslav에서 설명한 것과 동일한 설정으로 새 컨테이너를 다운로드, 중지 및 다시 시작하려는 경우) WatchTower를 사용할 수 있다고 덧붙이고 싶습니다. 컨테이너가 변경 될 때 컨테이너를 자동으로 업데이트하는 프로그램 https://github.com/v2tec/watchtower


20

이 답변을 고려하십시오.

  • 데이터베이스 이름은 app_schema
  • 컨테이너 이름은 app_db
  • 루트 비밀번호는 root123

컨테이너 내에 애플리케이션 데이터를 저장할 때 MySQL을 업데이트하는 방법

컨테이너를 잃으면 데이터를 잃을 수 있기 때문에 이것은 나쁜 습관으로 간주 됩니다. 좋지 않은 방법이지만 여기에 가능한 방법이 있습니다.

1) 데이터베이스 덤프를 SQL로 수행하십시오.

docker exec app_db sh -c 'exec mysqldump app_schema -uroot -proot123' > database_dump.sql

2) 이미지를 업데이트하십시오.

docker pull mysql:5.6

3) 컨테이너를 업데이트하십시오.

docker rm -f app_db
docker run --name app_db --restart unless-stopped \
-e MYSQL_ROOT_PASSWORD=root123 \
-d mysql:5.6

4) 데이터베이스 덤프를 복원하십시오.

docker exec app_db sh -c 'exec mysql -uroot -proot123' < database_dump.sql

외부 볼륨을 사용하여 MySQL 컨테이너를 업데이트하는 방법

외부 볼륨을 사용하는 것이 데이터를 관리하는 더 좋은 방법이며 MySQL을보다 쉽게 ​​업데이트 할 수 있습니다. 컨테이너를 풀면 데이터가 손실되지 않습니다. docker-compose 를 사용 하여 단일 호스트에서 다중 컨테이너 Docker 응용 프로그램을 쉽게 관리 할 수 있습니다 .

1) docker-compose.yml응용 프로그램을 관리하기 위해 파일을 작성하십시오 .

version: '2'
services:
  app_db:
    image: mysql:5.6
    restart: unless-stopped
    volumes_from: app_db_data
  app_db_data:
    volumes: /my/data/dir:/var/lib/mysql

2) docker-compose.yml파일 과 동일한 폴더에서 MySQL을 업데이트 하십시오.

docker-compose pull
docker-compose up -d

참고 : 위의 마지막 명령은 MySQL 이미지를 업데이트하고 새 이미지로 컨테이너를 다시 만들고 시작합니다.


거대한 데이터베이스 (몇 GB)가 있다고 가정 해 보겠습니다. 전체 데이터베이스를 가져올 때까지 내 데이터에 액세스 할 수 없습니까? 그것은 거대한 "다운 타임"일 수 있습니다
hellimac

당신이 언급 한 이후로 docker-compose, 이것이 효과가 있습니까? stackoverflow.com/a/31485685/65313
sivabudh

1
volumes_from키는 새 volumes키 를 위해 더 이상 사용되지 않습니다 (작성 파일의 버전 3에서도 제거됨) .
Franklin Yu

docker pull image_uri:tag && docker restart container_running_that_image나를 위해 일했다. 필요 없습니다 docker-compose pull && docker-compose up -d.
Yuriy Pozniak

16

위와 비슷한 답변

docker images | awk '{print $1}' | grep -v 'none' | grep -iv 'repo' | xargs -n1 docker pull

1
훌륭한! 더 많은 표를 얻지 못한 것에 놀랐습니다. 이제 누락 된 것은 업데이트 된 모든 컨테이너를 다시 시작하는 것입니다.
sorin

7
불행히도 기존 컨테이너는 업데이트되지 않습니다. 가져온 이미지 만 업데이트되지만 기존 컨테이너는 변경할 수 없으며 이미지를 만드는 데 사용 된 원본 이미지를 계속 사용합니다. 이미지에서 새 컨테이너를 만들지 만 기존 컨테이너가 여전히 원본 이미지를 기반으로하는 경우에만 작동합니다.
Eric B.

놀랄 만한. 컨테이너의 특정 버전을 가져와야하는 경우 다음과 같이하십시오. docker images | awk '{print $ 1 ":"$ 2}'| grep -v '없음'| grep -iv 'repo'| xargs -n1 도커 풀
rogervila

11

docker-composecustom 을 만들 때 사용하는 모습은 다음과 같습니다 Dockerfile.

  1. 차별화 할 다음 버전 번호를 추가하여 사용자 정의 Dockerfile을 먼저 빌드하십시오. 예 : docker build -t imagename:version . 새 버전을 로컬에 저장합니다.
  2. 운영 docker-compose down
  3. docker-compose.yml1 단계에서 설정 한 새 이미지 이름을 반영하도록 파일을 편집하십시오 .
  4. 를 실행하십시오 docker-compose up -d. 로컬에서 이미지를 찾고 업그레이드 된 이미지를 사용합니다.

-편집하다-

위의 단계는 필요한 것보다 더 장황합니다. build: .docker-compose 파일에 매개 변수를 포함시켜 작업 흐름을 최적화했습니다 . 단계는 이제 다음과 같습니다.

  1. 내 Dockerfile이 원하는 모양인지 확인하십시오.
  2. docker-compose 파일에서 이미지 이름의 버전 번호를 설정하십시오.
  3. 내 이미지가 아직 빌드되지 않은 경우 : 실행 docker-compose build
  4. 운영 docker-compose up -d

당시에는 알지 못했지만 docker-compose는 컨테이너를 먼저 내리지 않고 하나의 명령으로 컨테이너를 새 이미지로 업데이트하기에 충분합니다.


실제 상황에서는 자신의 손을 사용하여 변경할 수 없습니다. 귀하의 솔루션은 문제를 해결하는 자동 방법을 지원하지 않습니다.
카를로스 바스케스 Losada

7
그래서 당신은 내 솔루션이 자동화되어 있지 않기 때문에 유효하지 않다고 말하고 있습니다. OP의 요구 사항입니까? 그리고 다른 대답은 자동화를 암시합니까? 정말 혼란 스럽습니다. 그리고 다운 보트는 여기에 오는 다른 사람들에게 장애를 겪고 있다고 생각합니다. 내 답변은 질문에 100 % 유효합니다.
gdbj

이 답변에 감사드립니다. 또한 docker-compose up -d모든 것을 먼저 중지하지 않고도 간단하게 실행할 수 있다는 것을 알지 못했습니다 .
radicand

4

Docker Compose를 사용하지 않으려면 portainer 를 추천 할 수 있습니다 . 최신 이미지를 가져 오는 동안 컨테이너를 다시 만들 수있는 다시 작성 기능이 있습니다.


2

모든 이미지를 다시 빌드하고 모든 컨테이너를 다시 시작하거나 소프트웨어를 업데이트하고 데이터베이스를 다시 시작해야합니다. 업그레이드 경로는 없지만 직접 디자인하십시오.


컨테이너를 다시 시작한다는 것은 정확히 무엇을 의미합니까? 이 docker restart명령은,하지만 난 그것을 이미지 변경 사항을 적용합니다 모르겠습니다. 컨테이너 내 데이터는 어떻게됩니까?
Yaroslav Stavnichiy

1
죄송합니다. 도커를 다시 시작한다는 의미는 아닙니다. 나는 docker rm -f CONTANER를 의미한다. 도 커가 NEW_IMAGE를 실행합니다. SQL 컨테이너의 데이터가 사라집니다. 이것이 사람들이 일반적으로 데이터를 저장하기 위해 볼륨을 사용하는 이유입니다.
seanmcl

모든 데이터가 별도의 컨테이너 또는 호스트 시스템에 볼륨에 마운트되어 있으면 nas @seanmcl은 동일한 mysql에 동일한 데이터에 연결된 새 컨테이너를 생성한다고 말했습니다. 그렇게하지 않으면 (해야합니다) docker 1.3에서 사용 가능한 docker exec 명령을 사용하여 mysql을 업데이트하고 컨테이너 내부에서 다시 시작할 수 있습니다.
Usman Ismail

2

http://blog.stefanxo.com/2014/08/update-all-docker-images-at-once/ 에서 가져 오기

다음 명령 파이프 라인을 사용하여 기존 이미지를 모두 업데이트 할 수 있습니다.

docker images | awk '/^REPOSITORY|\<none\>/ {next} {print $1}' | xargs -n 1 docker pull

6
이미지는 업데이트되지만 컨테이너는 업데이트되지 않습니다. 컨테이너는 변경할 수 없으며 업데이트 된 이미지에서 새 컨테이너를 만들지 않으면 기본 이미지를 변경할 수 없습니다.
Eric B.

2

해당 컨테이너 내부의 프로세스 상태와 관련된 컨테이너에 저장하는 모든 영구 데이터 (구성, 로그 또는 응용 프로그램 데이터)에 볼륨을 사용하고 있는지 확인하십시오. Dockerfile을 업데이트하고 원하는 변경 사항으로 이미지를 다시 빌드하고 볼륨을 적절한 위치에 마운트하여 컨테이너를 다시 시작하십시오.


1

이것은 나 자신의 이미지를 위해 어려움을 겪고있는 것입니다. Docker 이미지를 생성하는 서버 환경이 있습니다. 서버를 업데이트 할 때 Docker 이미지를 기반으로 컨테이너를 실행하는 모든 사용자가 최신 서버로 업그레이드 할 수 있기를 바랍니다.

이상적으로는 새 버전의 Docker 이미지를 생성하고 해당 이미지의 이전 버전을 기반으로하는 모든 컨테이너를 새 이미지로 자동 업데이트하도록하는 것이 좋습니다. 그러나이 메커니즘은 존재하지 않는 것 같습니다.

따라서 지금까지 내가 생각해 낸 최고의 디자인은 컨테이너가 자체적으로 업데이트되도록하는 방법을 제공하는 것입니다. 데스크톱 응용 프로그램이 업데이트를 확인한 다음 자체적으로 업그레이드하는 방법과 비슷합니다. 필자의 경우 이것은 아마도 잘 알려진 태그에서 Git 풀을 포함하는 스크립트를 작성하는 것을 의미합니다.

이미지 / 컨테이너는 실제로 변경되지 않지만 해당 컨테이너의 "내부"는 변경됩니다. apt-get, yum 또는 환경에 적합한 것을 사용하여 동일한 작업을 수행하는 것을 상상할 수 있습니다. 이와 함께 레지스트리에서 myserver : latest 이미지를 업데이트하여 새 컨테이너가 최신 이미지를 기반으로하도록합니다.

이 시나리오를 다루는 선행 기술이 있는지 듣고 싶습니다.


7
그것은 불변 인프라의 개념과 그 이점 중 일부에 위배됩니다. 응용 프로그램 / 환경을 테스트하여 작동하는지 확인하고 내부 구성 요소를 업데이트해도 보장되지는 않습니다. 구성의 데이터에서 컨테이너 코드를 분할하면 테스트 된 이미지와 프로덕션 코드의 코드 라인이 다르므로 현재 작업하고 프로덕션에 배포하고 있는지 테스트하고 테스트 할 수 있습니다. 어쨌든, 시스템은 당신이 선택하는대로 당신이 말한대로 그것을 관리하게합니다.
gmuslera

아주 좋은 점 gmuslera. 기존 도커 컨테이너의 '내부'를 업데이트하는 것이 안티 패턴이라는 데 동의했습니다.
bjlevine

그렇다면 모든 컨테이너에 쉽게 업데이트를 제공하기 위해 도커 이미지 업데이트를 기반으로 도커 컨테이너를 자동 업데이트하는 가장 좋은 솔루션은 무엇입니까?
tarek salem

1

최신 정보

이것은 주로 이미지 빌드가 수행되는 방식이므로 컨테이너가 업데이트하지 않도록 쿼리하는 것입니다.

동일한 문제가 발생하여 docker-run을 만들었습니다 . Docker 컨테이너 내 에서 실행되어 다른 실행중인 컨테이너의 패키지를 업데이트 하는 매우 간단한 명령 줄 도구입니다 .

docker-py 를 사용 하여 실행중인 docker 컨테이너와 통신하고 패키지를 업데이트하거나 임의의 단일 명령을 실행합니다.

예 :

docker run --rm -v /var/run/docker.sock:/tmp/docker.sock itech/docker-run exec

기본적으로 이것은 date실행중인 모든 컨테이너에서 명령을 실행하고 결과를 반환하지만 다음과 같은 명령을 실행할 수 있습니다docker-run exec "uname -a"

패키지를 업데이트하려면 (현재 apt-get 만 사용) :

docker run --rm -v /var/run/docker.sock:/tmp/docker.sock itech/docker-run update

예를 들어 별칭을 생성하고 일반 명령 줄로 사용할 수 있습니다.

alias docker-run='docker run --rm -v /var/run/docker.sock:/tmp/docker.sock itech/docker-run'


이것이 좋은 생각입니까? (그렇게 apt update; apt upgrade하면 이미지가 커집니다.)
ctrl-alt-delor

@ yaroslav의 이미지는이 문제에 대한 더 나은 해결책입니다. 위의 작업이 실제로 도커 방식이 아닙니다.
Joost van der Laan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.