Görüntü değiştikten sonra liman işçisi konteyneri nasıl yükseltilir


518

Resmi mysql: 5.6.21 görüntüsünü çektim diyelim .

Bu görüntüyü birkaç liman işçisi konteyneri oluşturarak dağıttım.

Bu kapsayıcılar bir süredir MySQL 5.6.22 piyasaya sürüldü. Mysql: 5.6'nın resmi resmi yeni sürümle güncelleniyor, ancak kaplarım yine de 5.6.21 çalıştırıyor.

Görüntüdeki değişiklikleri (yani MySQL dağıtımını yükselt) mevcut tüm kaplarıma nasıl yayabilirim? Bunu yapmanın uygun Docker yolu nedir?

Yanıtlar:


578

Cevapları değerlendirdikten ve konuyu inceledikten sonra özetlemek istiyorum.

Kapsayıcıları yükseltmenin Docker yolu aşağıdaki gibi görünüyor:

Uygulama kapları uygulama verilerini depolamamalıdır . Bu şekilde, uygulama kapsayıcısını yeni sürümüyle istediğiniz zaman aşağıdaki gibi bir şey yürütebilirsiniz:

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

Verileri ana bilgisayarda (birim olarak monte edilen dizinde) veya yalnızca özel veri kaplarında depolayabilirsiniz . Bununla ilgili daha fazla bilgi edinin

Kapların içindeki uygulamaların yükseltilmesi (örn. Yum / apt-get yükseltmesi ile) bir anti-desen olarak kabul edilir . Uygulama kaplarının, tekrarlanabilir davranışı garanti edecek şekilde değiştirilemez olduğu varsayılmaktadır . Bazı resmi uygulama görüntüleri (özellikle mysql: 5.6) kendi kendini güncellemek için tasarlanmamıştır (apt-get yükseltme çalışmaz).

Yanıtlarını veren herkese teşekkür etmek istiyorum, böylece tüm farklı yaklaşımları görebiliriz.


31
Veri taşıma gerekiyorsa ne olur? Yeni sunucu verileri eski bir biçimde olduğu için bağlayamaz, bir geçişin gerçekleştiğini bilmeli ve veri sunumunu değiştirmelidir.
Dor Rotman

12
Bence, görüntü tasarımcıları bunu hesaba katmalı ve kabın ilk çalışması sırasında özel (örn. Veri taşıma) komutlarının başlatılmasına izin vermelidir.
Yaroslav Stavnichiy


4
@static_rtti Yenisini docker rename my-mysql-container trash-containeroluşturmadan önce ne dersiniz ?
Franklin Yu

4
Kapsayıcıyı el ile durdurmaya, kaldırmaya ve yeniden oluşturmaya gerek kalmadan güncellemek için bir all-in-one komutu olur mu?
Michaël Perrin

83

Bir ana bilgisayar dizinine bağlantı olarak birimler bağlamayı sevmiyorum, bu yüzden docker kaplarını tamamen docker yönetimli kaplarla yükseltmek için bir desen buldum. İle yeni bir liman işçisi konteyneri oluşturduğunuzda --volumes-from <container>, yeni konteynere docker yönetilen birimlerin güncellenmiş görüntüleri paylaşılır.

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

my_mysql_containerHenüz orijinali hemen çıkarmayarak, yükseltilmiş konteyner doğru verilere sahip değilse veya bir sağlık testi yapamazsa, bilinen çalışma kabına geri dönme olanağına sahip olursunuz.

Bu noktada, genellikle bir şeylerin yanlış gitmesi durumunda konteynerin kendime bir güvenlik ağı vermesi için sahip olduğum yedekleme komut dosyalarını çalıştırırım.

docker stop my_mysql_container
docker start my_mysql_container_tmp

Artık yeni kapta olmasını beklediğiniz verilerin orada olduğundan emin olun ve bir sağlık kontrolü yapın.

docker rm my_mysql_container
docker rename my_mysql_container_tmp my_mysql_container

Yükleme istasyonu hacimleri, herhangi bir kabı kullandıkları sürece yapışacaktır, böylece orijinal kabı güvenle silebilirsiniz. Orijinal kap çıkarıldıktan sonra, yeni kap, her şeyin başlayacağı kadar güzel olmasını sağlamak için orijinalin adını alabilir.

Docker kaplarını yükseltmek için bu kalıbı kullanmanın iki büyük avantajı vardır. İlk olarak, birimlerin doğrudan yükseltilmiş kaplara aktarılmasına izin vererek birimlerin ana bilgisayar dizinlerine bağlanması gereğini ortadan kaldırır. İkincisi, asla çalışan bir liman işçisi konteynerinin olmadığı bir konumda değilsiniz; bu nedenle yükseltme başarısız olursa, orijinal docker kapsayıcısını tekrar açarak daha önce nasıl çalıştığına kolayca dönebilirsiniz.


3
Ana bilgisayar birimlerini Docker kapsayıcısına neden eklemeyi sevmiyorsunuz? (Ben tam olarak bunu yapmak karşı argümanlarla ilgileniyorum yapıyorum: -) Örneğin monte ettik: ./postgres-data/:/var/lib/postgres/data- yani ./postgres-data/benim PostgreSQL kapsayıcı içinde host dir monte .)
KajMagnus

4
@KajMagnus Docker sürüleri çok kullanıyorum ve konteynerlerimi bir sürüde iyi çalışmak için yazmaktan hoşlanıyorum. Bir konteyneri bir sürüde döndürdüğümde, konteynerin hangi sürü düğümü üzerinde yaşayacağına dair hiçbir fikrim yok, bu yüzden istediğim verileri içeren ana bilgisayar yoluna güvenemiyorum. Docker 1.9 (sanırım) birimler, tarif ettiğim yöntemi kullanarak kapları yükseltme ve geçirmeyi bir esinti haline getiren ana bilgisayarlar arasında paylaşılabilir. Bir alternatif, tüm ağ sürüsü düğümlerine bir miktar ağ hacminin monte edildiğinden emin olmaktır, ancak bu, bakımı büyük bir acı gibi görünebilir.
kMaiSmith

Teşekkürler! Tamam, anasistem birimlerini takmak artık kaçınmak istediğim bir şey gibi görünüyor. Uygulamam popüler hale gelirse ve birden fazla sunucuya ölçeklendirilmek gerekirse en azından biraz sonra
KajMagnus

32

Sadece daha genel (mysql'e özgü değil) bir cevap sağlamak için ...

  1. Kısacası

Servis resmi kayıt defteri ile senkronize etme ( https://docs.docker.com/compose/compose-file/#image ):

docker-compose pull 

Bağlantı birimi oluşturma dosyası veya resmi değiştiyse kapsayıcıyı yeniden oluşturun:

docker-compose up -d
  1. Arka fon

Kapsayıcı resim yönetimi, docker-compose kullanmanın nedenlerinden biridir (bkz. Https://docs.docker.com/compose/reference/up/ )

Bir hizmet için mevcut kapsayıcılar varsa ve kapsayıcının oluşturulmasından sonra hizmetin yapılandırması veya görüntüsü değiştirilmişse, liman işçisi oluşturma, kapları durdurarak ve yeniden oluşturarak (takılı birimleri koruyarak) değişiklikleri alır. Compose'un değişiklikleri toplamasını önlemek için --no-rekre bayrağını kullanın.

Veri yönetimi boyutu, bağlı harici "birimler" (Bkz. Https://docs.docker.com/compose/compose-file/#volumes ) veya veri taşıyıcısı aracılığıyla docker-compose tarafından da kapsanmaktadır .

Bu, geriye dönük uyumluluk ve veri taşıma sorunlarına dokunulmaz, ancak bunlar sürüm notlarına ve testlere karşı kontrol edilmesi gereken Docker'a özgü değil "uygulanabilir" konulardır ...


Sürüm oluşturmada bunu nasıl yapıyorsunuz? örnek yeni görüntü foo / image: 2 ve docker-compose.yml öğesinde image: foo / image: 1?
dman

TEŞEKKÜR EDERİM. En iyi cevap!
Mick

Bu kesinlikle gidilecek yol olsa da, konteyner yeniden oluşturulduktan sonra konteynerde yapılan değişikliklerin kaybolacağının farkında olunmalıdır. Bu nedenle, konteyner değişikliklerini sadece monte edilmiş birimler içinde tutmak hala gereklidir.
Petr Bodnár

23

Bu işlemi otomatik olarak yapmak istiyorsanız (@Yaroslav tarafından açıklanan ayarlarla yeni bir kapsayıcıyı indirin, durdurun ve yeniden başlatın) WatchTower'ı kullanabileceğinizi eklemek isterim. Değiştirildiklerinde kaplarınızı otomatik olarak güncelleyen bir program https://github.com/v2tec/watchtower


20

Bu cevapları düşünün:

  • Veritabanı adı app_schema
  • Kapsayıcı adı app_db
  • Root şifresi root123

Uygulama verilerini kapsayıcıya kaydederken MySQL nasıl güncellenir?

Bu kötü bir uygulama olarak kabul edilir , çünkü konteyneri kaybederseniz verileri kaybedersiniz. Kötü bir uygulama olmasına rağmen, bunu yapmanın olası bir yolu:

1) SQL olarak bir veritabanı dökümü yapın:

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

2) Resmi güncelleyin:

docker pull mysql:5.6

3) Konteyner güncelleyin:

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

4) Veritabanı dökümü geri yükleyin:

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

Harici bir birim kullanarak MySQL kapsayıcısını güncelleme

Harici bir birimi kullanmak, verileri yönetmenin daha iyi bir yoludur ve MySQL'in güncellenmesini kolaylaştırır. Kapsayıcıyı kaybetmek veri kaybetmez. Çok kapsayıcı Docker uygulamalarını tek bir ana bilgisayarda yönetmeyi kolaylaştırmak için docker-compose komutunu kullanabilirsiniz :

1) docker-compose.ymlUygulamalarınızı yönetmek için dosyayı oluşturun :

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) MySQL'i güncelleyin ( docker-compose.ymldosya ile aynı klasörden ):

docker-compose pull
docker-compose up -d

Not: yukarıdaki son komut MySQL görüntüsünü güncelleyecek, yeni görüntüyle kapsayıcıyı yeniden oluşturacak ve başlatacaktır.


Diyelim ki büyük bir veritabanım var (birkaç GB), tüm veritabanı içe aktarılana kadar verilerime erişilemez mi? Bu büyük bir "kesinti süresi" olabilir
hellimac

Bahsettiğinizden docker-composebu işe yarar mı? stackoverflow.com/a/31485685/65313
sivabudh

1
volumes_fromanahtarı artık yeni volumesanahtar lehine kullanımdan kaldırılmıştır (beste dosyasının 3. sürümünde bile kaldırılmıştır) .
Franklin Yu

docker pull image_uri:tag && docker restart container_running_that_imagebenim için çalıştı. Gerek yok docker-compose pull && docker-compose up -d.
Yuriy Pozniak

16

Yukarıdakine benzer cevap

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

1
Parlak! Daha fazla oy alamadığı için oldukça şaşırdım. Şimdi eksik olan tek şey güncellenen tüm kapların yeniden başlatılmasını tetiklemek olacaktır.
sorin

7
Ne yazık ki bu mevcut kapsayıcıyı güncellemeyecek. Bu sadece çekilen görüntüyü güncelleyecektir, ancak mevcut kapsayıcı değişmezdir ve hala oluşturmak için kullanılan orijinal görüntüyü kullanır. Bu, yalnızca görüntüden yeni bir kapsayıcı oluşturduğunuzda çalışır, ancak varolan herhangi bir kapsayıcı yine de orijinal görüntüyü temel alır.
Eric B.

İnanılmaz. Kabın belirli bir sürümünü çekmeniz gerekiyorsa, şu şekilde yapın: docker görüntüleri | awk '{print $ 1 ":" 2 $}' | grep -v 'hiçbiri' | grep -iv 'repo' | xargs -n1 liman işçisi çekme
rogervila

11

docker-composeBir özel oluştururken böyle görünüyor Dockerfile.

  1. Farklılaştırmak için bir sonraki sürüm numarası ekleyerek önce özel Dockerfile dosyanızı oluşturun. Örn: docker build -t imagename:version . Bu, yeni sürümünüzü yerel olarak depolar.
  2. Çalıştırmak docker-compose down
  3. Senin Düzenleme docker-compose.ymldosya 1. adımda belirlenen yeni resim adını yansıtacak şekilde.
  4. Koş docker-compose up -d. Görüntüyü yerel olarak arayacak ve yükseltilen görüntünüzü kullanacaktır.

-DÜZENLE-

Yukarıdaki adımlarım olması gerekenden daha ayrıntılı. build: .Parametreyi docker-compose dosyasına ekleyerek iş akışımı optimize ettim . Adımlar şu şekilde görünüyor:

  1. Dockerfile'ımın görünmesini istediğim şey olduğunu doğrulayın.
  2. Docker-compose dosyamda resim adımın sürüm numarasını ayarlayın.
  3. Resmim henüz oluşturulmadıysa: çalıştır docker-compose build
  4. Çalıştırmak docker-compose up -d

O zaman fark etmedim, ancak docker-compose, kapsayıcıyı yeni görüntüye tek komutla güncellemek için yeterince akıllı, önce onu aşağı çekmek yerine.


Gerçek bir durumda kendi ellerinizi kullanamaz ve bu değişiklikleri yapamazsınız. Çözümünüz sorunu çözmek için otomatik yolları desteklemiyor.
Carlos Vázquez Losada

7
yani benim çözümüm otomatik olmadığı için geçerli olmadığını mı söylüyorsunuz? Bu OP'den bir gereklilik mi? Diğer cevaplar otomasyonu mu ima ediyor? Gerçekten şaşkın. Ve sanırım inişler buraya gelenlere karşı bir kötülük yapıyor. Cevabım, sorulan soru için% 100 geçerli.
gdbj

Bu cevap için teşekkürler, docker-compose up -dilk önce her şeyi durdurmaya gerek kalmadan koşabileceğinizin farkında değildim .
radicand

4

Docker Compose kullanmak istemiyorsanız, portainer önerebilirim . En son görüntüyü çekerken bir kabı yeniden oluşturmanıza olanak tanıyan bir yeniden oluşturma işlevine sahiptir.


2

Tüm görüntüleri yeniden oluşturup tüm kapsayıcıları yeniden başlatmanız veya bir şekilde yum'u güncelleştirmeniz ve veritabanını yeniden başlatmanız gerekir. Yükseltme yolu yok ama kendiniz tasarlıyorsunuz.


Kapları yeniden başlatarak tam olarak ne demek istiyorsun? Orada docker restartkomut, ama görüntü değişiklikleri almak olacaktır emin değilim. Kapsayıcılar içindeki verilerime ne olacak?
Yaroslav Stavnichiy

1
Üzgünüm, docker'ın yeniden başlatılması demek istemedim. Demek istediğim docker rm -f CONTANER; docker çalıştırmak NEW_IMAGE. Sql kabınızdaki veriler kaybolacaktır. Bu yüzden insanlar genellikle verileri depolamak için hacimler kullanırlar.
seanmcl

Tüm verileriniz ayrı kaplarda veya ana makinede birimlere monte edilmişse, nas @seanmcl aynı verilere bağlı yeni mysql ile yeni kaplar oluşturduğunu söyledi. Bunu yapmadıysanız (yapmanız gerekir), ancak mysql'i güncellemek ve kap içinde yeniden başlatmak için docker 1.3'te bulunan docker exec komutunu kullanabilirsiniz.
Usman Ismail

2

Alarak http://blog.stefanxo.com/2014/08/update-all-docker-images-at-once/

Aşağıdaki komut kanalını kullanarak mevcut tüm görüntülerinizi güncelleyebilirsiniz:

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

6
Bu görüntüleri günceller, ancak kapsayıcıyı güncellemez. Kap değiştirilemez ve temel görüntü, güncellenmiş bir görüntüden yeni bir kap oluşturmadan değiştirilemez.
Eric B.

2

Kaplarda sakladığınız tüm kalıcı veriler (yapılandırma, günlükler veya uygulama verileri) için birimler kullandığınızdan emin olun. Dockerfile'ınızı güncelleyin ve görüntüyü istediğiniz değişikliklerle yeniden oluşturun ve birimlerinizi uygun yerlere monte edilmiş olarak yeniden başlatın.


1

Bu, kendi görüntülerim için de mücadele ettiğim bir şey. Docker görüntüsü oluşturduğum bir sunucu ortamım var. Sunucuyu güncellediğimde, Docker resmimi temel alan kaplar çalıştıran tüm kullanıcıların en son sunucuya yükseltme yapabilmelerini istiyorum.

İdeal olarak, Docker görüntüsünün yeni bir sürümünü oluşturmayı ve bu görüntünün önceki bir sürümüne dayanan tüm kapsayıcıları otomatik olarak "yerinde" yeni görüntüye güncellemeyi tercih ederim. Fakat bu mekanizma var gibi görünmüyor.

Bu yüzden şimdiye kadar ortaya koyabildiğim bir sonraki en iyi tasarım, bir masaüstü uygulamasının güncellemeleri nasıl kontrol edip yükselttiğine benzer şekilde, kabın kendisini güncellemesinin bir yolunu sağlamaktır. Benim durumumda, bu muhtemelen Git'in iyi bilinen bir etiketten çektiği bir komut dosyası hazırlamak anlamına gelecektir.

Görüntü / kap aslında değişmez, ancak kapın "iç öğeleri" değişir. Aynı şeyi apt-get, yum veya ortamınız için uygun olan her şeyle de yapabilirsiniz. Bununla birlikte, yeni kapsayıcıların en son görüntüye dayanması için kayıt defterindeki myserver: latest görüntüsünü güncellerdim.

Bu senaryoyu ele alan önceki tekniklerin olup olmadığını duymak isterim.


7
Değişmez altyapı kavramına ve bazı faydalarına aykırıdır. Uygulamanızın / ortamınızın çalıştığını görmek için test edebilirsiniz ve içindeki bileşenleri güncellediğinizde garanti edilmez. Kapsayıcı kodunu yapılandırmadan verilerden ayırmak, test edilen görüntüden üretime kadar farklı bir kod satırı olmadığını bilerek güncellemenizi, şu anda çalıştığımızı test etmemizi ve üretime dağıtmamızı sağlar. Her neyse, sistem sizin de dediğiniz gibi yönetmenize izin veriyor, seçim sizin.
gmuslera

Çok iyi bir nokta gmuslera. Mevcut bir docker konteynerinin 'iç bileşenlerini' güncellemenin bir anti-desen olduğunu kabul etti.
bjlevine

Peki, tüm kapsayıcılara zahmetsizce güncellemeler sağlamak için docker kapsayıcısı görüntü güncellemelerine dayanarak docker kapsayıcısını otomatik olarak güncellemenin en iyi çözümü nedir?
tarek salem

1

Güncelleme

Bu esas olarak bina görüntüleri yapılması için yol olduğu için güncelleme değil konteyner sorgulamak için

Aynı sorun vardı, bu yüzden diğer çalışan kapsayıcılarda paketleri güncellemek için bir docker kapsayıcısının içinde çalışan çok basit bir komut satırı aracı olan docker-run oluşturdum .

Çalışan docker kaplarıyla iletişim kurmak ve paketleri güncellemek veya herhangi bir keyfi tek komutu çalıştırmak için docker-py kullanır

Örnekler:

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

varsayılan olarak bu datetüm çalışan kapsayıcılarda komut çalıştırır ve sonuçları döndürür ancak herhangi bir komut verebilirsiniz.docker-run exec "uname -a"

Paketleri güncellemek için (şu anda yalnızca apt-get kullanıyor):

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

Oluşturup diğer ad ve normal komut satırı olarak kullanabilirsiniz, ör.

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


Bu iyi bir fikir mi? (Eğer yaparsanız apt update; apt upgrade, görüntü büyüyecektir.)
ctrl-alt-delor

@yaroslav s imajı bu soruna daha iyi bir çözümdür. Yukarıdakiler aslında Docker'ın bir şeyler yapmanın yolu değil.
Joost van der Laan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.