이미지가 변경된 후 도커 컨테이너를 업그레이드하는 방법
공식 mysql : 5.6.21 image를 가져 왔다고 가정 해 봅시다 .
여러 도커 컨테이너를 만들어이 이미지를 배포했습니다.
이 컨테이너는 MySQL 5.6.22가 출시 될 때까지 얼마 동안 실행되었습니다. mysql : 5.6의 공식 이미지는 새로운 릴리스로 업데이트되지만 컨테이너는 여전히 5.6.21로 실행됩니다.
이미지의 변경 사항 (예 : MySQL 배포판 업그레이드)을 기존의 모든 컨테이너에 어떻게 전파합니까? 이 작업을 수행하는 올바른 Docker 방법은 무엇입니까?
답변을 평가하고 주제를 연구 한 후 요약하고 싶습니다.
컨테이너를 업그레이드하는 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
호스트 (볼륨으로 마운트 된 디렉토리) 또는 특수 데이터 전용 컨테이너 에 데이터를 저장할 수 있습니다 . 그것에 대해 더 읽어보기
- 볼륨 정보 (Docker 문서)
- 작은 도커 조각, 느슨하게 결합 됨 (Tom Offermann)
- Docker에서 영구 저장소 (예 : 데이터베이스)를 처리하는 방법 (스택 오버플로 질문)
컨테이너 내에서 업그레이드 응용 프로그램 (예 : yum / apt-get 업그레이드)은 안티 패턴으로 간주됩니다 . 어플리케이션 컨테이너는 변경 불가능 하며, 이는 재현 가능한 동작을 보장합니다. 일부 공식 응용 프로그램 이미지 (특히 mysql : 5.6)는 자체 업데이트하도록 설계되지 않았습니다 (apt-get 업그레이드가 작동하지 않음).
답변을 해주신 모든 분들께 감사 드리며, 다른 접근법을 모두보실 수 있습니다.
볼륨을 호스트 디렉토리에 대한 링크로 마운트하는 것을 좋아하지 않으므로 완전히 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
컨테이너가 컨테이너를 사용하는 동안 도커 볼륨이 달라 붙어 원래 컨테이너를 안전하게 삭제할 수 있습니다. 원래 컨테이너가 제거되면 새 컨테이너는 원래 이름을 그대로 사용하여 모든 것을 처음부터 예쁘게 만들 수 있습니다.
도커 컨테이너를 업그레이드하기 위해이 패턴을 사용하면 두 가지 주요 이점이 있습니다. 첫째, 볼륨을 업그레이드 된 컨테이너로 직접 전송할 수 있도록하여 호스트를 호스트에 볼륨을 마운트 할 필요가 없습니다. 두 번째로, 도커 컨테이너가 작동하지 않는 위치에 있지 않습니다. 따라서 업그레이드에 실패하면 원래 도커 컨테이너를 다시 회전시켜 이전의 작동 방식으로 쉽게 되돌릴 수 있습니다.
이 프로세스를 자동으로 수행하려면 (@Yaroslav에서 설명한 것과 동일한 설정으로 새 컨테이너를 다운로드, 중지 및 다시 시작하려는 경우) WatchTower를 사용할 수 있다고 덧붙이고 싶습니다. 컨테이너가 변경 될 때 컨테이너를 자동으로 업데이트하는 프로그램 https://github.com/v2tec/watchtower
더 일반적인 (mysql에 국한되지 않은) 답변을 제공하기 위해 ...
- 한마디로
서비스 이미지 레지스트리 ( https://docs.docker.com/compose/compose-file/#image ) 와 동기화 하십시오 .
docker-compose pull
docker-compose 파일 또는 이미지가 변경된 경우 컨테이너를 다시 만듭니다.
docker-compose up -d
- 배경
컨테이너 이미지 관리는 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가 아닌 "응용 적"문제이며 릴리스 정보 및 테스트와 비교하여 확인해야합니다 ...
이 답변을 고려하십시오.
- 데이터베이스 이름은
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 이미지를 업데이트하고 새 이미지로 컨테이너를 다시 만들고 시작합니다.
위와 비슷한 답변
docker images | awk '{print $1}' | grep -v 'none' | grep -iv 'repo' | xargs -n1 docker pull
docker-compose
custom 을 만들 때 사용하는 모습은 다음과 같습니다 Dockerfile
.
- 차별화 할 다음 버전 번호를 추가하여 사용자 정의 Dockerfile을 먼저 빌드하십시오. 예 :
docker build -t imagename:version .
새 버전을 로컬에 저장합니다. - 운영
docker-compose down
docker-compose.yml
1 단계에서 설정 한 새 이미지 이름을 반영하도록 파일을 편집하십시오 .- 를 실행하십시오
docker-compose up -d
. 로컬에서 이미지를 찾고 업그레이드 된 이미지를 사용합니다.
-편집하다-
위의 단계는 필요한 것보다 더 장황합니다. build: .
docker-compose 파일에 매개 변수를 포함시켜 워크 플로를 최적화했습니다 . 단계는 이제 다음과 같습니다.
- 내 Dockerfile이 원하는 모양인지 확인하십시오.
- docker-compose 파일에서 이미지 이름의 버전 번호를 설정하십시오.
- 내 이미지가 아직 빌드되지 않은 경우 : 실행
docker-compose build
- 운영
docker-compose up -d
당시에는 알지 못했지만 docker-compose는 컨테이너를 먼저 내리는 대신 하나의 명령으로 컨테이너를 새 이미지로 업데이트하기에 충분합니다.
Docker Compose를 사용하지 않으려면 portainer 을 추천 할 수 있습니다 . 최신 이미지를 가져 오는 동안 컨테이너를 다시 만들 수있는 다시 작성 기능이 있습니다.
모든 이미지를 다시 빌드하고 모든 컨테이너를 다시 시작하거나 소프트웨어를 업데이트하고 데이터베이스를 다시 시작해야합니다. 업그레이드 경로는 없지만 직접 디자인하십시오.
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
동일한 문제가 발생하여 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'
해당 컨테이너 내부의 프로세스 상태와 관련된 컨테이너에 저장하는 모든 영구 데이터 (구성, 로그 또는 응용 프로그램 데이터)에 볼륨을 사용하고 있는지 확인하십시오. Dockerfile을 업데이트하고 원하는 변경 사항으로 이미지를 다시 빌드하고 볼륨을 적절한 위치에 마운트하여 컨테이너를 다시 시작하십시오.
이것은 나 자신의 이미지를 위해 어려움을 겪고있는 것입니다. Docker 이미지를 생성하는 서버 환경이 있습니다. 서버를 업데이트 할 때 Docker 이미지를 기반으로 컨테이너를 실행하는 모든 사용자가 최신 서버로 업그레이드 할 수 있기를 바랍니다.
이상적으로는 새 버전의 Docker 이미지를 생성하고 해당 이미지의 이전 버전을 기반으로하는 모든 컨테이너를 새 이미지로 자동 업데이트하도록하는 것이 좋습니다. 그러나이 메커니즘은 존재하지 않는 것 같습니다.
따라서 지금까지 내가 생각해 낸 다음 최고의 디자인은 컨테이너를 자체적으로 업데이트하는 방법을 제공하는 것입니다. 데스크톱 응용 프로그램이 업데이트를 확인한 다음 자체적으로 업그레이드하는 방식과 유사합니다. 필자의 경우 이것은 아마도 잘 알려진 태그에서 Git 풀을 포함하는 스크립트를 만드는 것을 의미합니다.
이미지 / 컨테이너는 실제로 변경되지 않지만 해당 컨테이너의 "내부"는 변경됩니다. apt-get, yum 또는 환경에 적합한 것을 사용하여 동일한 작업을 수행하는 것을 상상할 수 있습니다. 이와 함께 레지스트리에서 myserver : latest 이미지를 업데이트하여 새 컨테이너가 최신 이미지를 기반으로하도록합니다.
이 시나리오를 다루는 선행 기술이 있는지 듣고 싶습니다.
업데이트하려는 컨테이너가 docker-compose 그룹의 일부이지만 다음 두 명령으로 개별 컨테이너를 업데이트 할 수 있습니다.
docker pull image.uri.io:latest
docker restart the-container
제공하는
docker ps --format 'table{{.Names}}\t{{.Image}}'
NAMES IMAGE
the-container image.uri.io:latest
이 방법의 장점은 @Yaroslav의 답변docker run
에서와 같이 모든 생성 매개 변수 를 실행 하고 반복 할 필요가 없다는 것 입니다.
참고 URL : https://stackoverflow.com/questions/26734402/how-to-upgrade-docker-container-after-its-image-changed
'Programing' 카테고리의 다른 글
Java Swing에서 set (Preferred | Maximum | Minimum) Size 메서드를 사용하지 않아야합니까? (0) | 2020.02.15 |
---|---|
int argc, char * argv []은 무슨 뜻인가요? (0) | 2020.02.15 |
쉘 스크립트에서 줄 바꿈이없는 'echo' (0) | 2020.02.15 |
jQuery는 텍스트를 얻는다 (0) | 2020.02.15 |
jQuery $ (문서) .ready 및 UpdatePanels? (0) | 2020.02.15 |