ฉันจะเพิ่มปริมาณให้กับคอนเทนเนอร์ Docker ที่มีอยู่ได้อย่างไร


297

ฉันมีคอนเทนเนอร์ Docker ที่ฉันสร้างขึ้นโดยติดตั้ง Docker บน Ubuntu และทำ:

sudo docker run -i -t ubuntu /bin/bash

ฉันเริ่มติดตั้ง Java และเครื่องมืออื่น ๆ ทันทีใช้เวลากับมันและหยุดการทำงานของคอนเทนเนอร์

exit

จากนั้นฉันต้องการเพิ่มปริมาณและตระหนักว่าสิ่งนี้ไม่ตรงไปตรงมาอย่างที่ฉันคิดไว้ ถ้าฉันใช้sudo docker -v /somedir run ...แล้วฉันจะจบด้วยคอนเทนเนอร์ใหม่ที่สดใหม่ดังนั้นฉันจะต้องติดตั้ง Java และทำสิ่งที่ฉันได้ทำไปแล้วก่อนที่จะมาถึงที่ภาชนะที่มีปริมาณการติดตั้ง

เอกสารทั้งหมดเกี่ยวกับการติดตั้งโฟลเดอร์จากโฮสต์ดูเหมือนจะบอกเป็นนัยว่าการติดตั้งไดรฟ์ข้อมูลเป็นสิ่งที่สามารถทำได้เมื่อสร้างคอนเทนเนอร์ ตัวเลือกเดียวที่ฉันต้องหลีกเลี่ยงการกำหนดค่าคอนเทนเนอร์ใหม่ตั้งแต่เริ่มต้นคือการยอมรับคอนเทนเนอร์ที่มีอยู่กับที่เก็บและใช้เป็นพื้นฐานของคอนเทนเนอร์ใหม่ในขณะที่ติดตั้งไดรฟ์

นี่เป็นวิธีเดียวที่จะเพิ่มโวลุ่มไปยังคอนเทนเนอร์ที่มีอยู่ได้หรือไม่?


1
หลังจากที่บรรจุเหล่านี้กลายเป็นส่วนหนึ่งของโปรแกรมเมอร์และด้วยเหตุนี้คำถามดังกล่าวจะโพสต์บ่อยขึ้นที่นี่ คำถามที่โพสต์ที่นี่โดยใช้dockerแท็กคือ34k +ซึ่งมากกว่าสองเว็บไซต์stackoverflow.com/questions/tagged/docker
MA Hossain Tonu

คำตอบ:


394

คุณสามารถคอมมิทคอนเทนเนอร์ที่มีอยู่ของคุณ (นั่นคือการสร้างอิมเมจใหม่จากการเปลี่ยนแปลงของคอนเทนเนอร์) จากนั้นรันด้วยการเมานต์ใหม่ของคุณ

ตัวอย่าง:

$ docker ps  -a
CONTAINER ID        IMAGE                 COMMAND                  CREATED              STATUS                          PORTS               NAMES
    5a8f89adeead        ubuntu:14.04          "/bin/bash"              About a minute ago   Exited (0) About a minute ago                       agitated_newton

$ docker commit 5a8f89adeead newimagename

$ docker run -ti -v "$PWD/dir1":/dir1 -v "$PWD/dir2":/dir2 newimagename /bin/bash

หากไม่เป็นไรให้หยุดภาชนะเก่าของคุณแล้วใช้อันใหม่นี้

แค่นั้นแหละ :)


22
และถ้าคุณต้องการคอนเทนเนอร์ใหม่ที่จะใช้ชื่อเก่าด้วยเหตุผลบางอย่างให้ใช้นักเทียบท่าเปลี่ยนชื่อหลังจากลบเก่า
เดิร์ค

10
แค่ต้องการชี้ให้เห็นว่าข้างต้นที่คุณพูดถึงnewnameofcontainerว่าควรมีชื่อนี้new_image_nameเพราะdocker commitสร้างภาพใหม่ในระบบของคุณ จากนั้นในต่อไปนี้เมื่อคุณทำdocker runคุณใช้ชื่อจริงของภาพที่คุณต้องการเรียกใช้คอนเทนเนอร์ใหม่ การทำงานด้านบน แต่ต้องการอธิบายให้ผู้อื่นทราบว่าชื่อใหม่ของตัวยึดตำแหน่งด้านบนนั้นเป็นชื่อของรูปภาพใหม่ ขอบคุณ! คำตอบที่น่ากลัว โอ้คุณสามารถเห็นภาพที่สร้างขึ้นใหม่จากคำสั่งนักเทียบท่าแรกใช้docker image ls
FireDragon

3
ในความเป็นจริงคุณไม่จำเป็นต้องผูกคอนเทนเนอร์ใหม่หากคุณต้องการเริ่มจากรูปภาพ เพียงแค่docker run -v /srv/a:/tmp ubuntu:14.04เป็นสิ่งที่ดี
YongHao Hu

ฉันมีคอนเทนเนอร์ที่ทำงานกับไฟล์ทั้งหมดแล้ว หากวิธีการดังกล่าวสร้างที่เก็บใหม่ฉันไม่สามารถสร้างทุกอย่างได้อีกครั้ง มีวิธีที่ฉันสามารถหลีกเลี่ยงปัญหานี้และติดตั้งโดยไม่ต้องสร้างภาชนะหรือรูปภาพใหม่หรือไม่?
dhinar

สิ่งนี้จะทำให้การแมปปริมาณมากจากคอนเทนเนอร์เก่าหรือฉันควรประกาศใหม่ด้วยคอนเทนเนอร์ใหม่ด้วยหรือไม่
thebeancounter

79

เราไม่มีวิธีเพิ่มปริมาณในคอนเทนเนอร์ที่ใช้งาน แต่เพื่อให้บรรลุวัตถุประสงค์นี้คุณอาจใช้คำสั่งด้านล่าง:

คัดลอกไฟล์ / โฟลเดอร์ระหว่างคอนเทนเนอร์และระบบไฟล์โลคอล: -

docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-

docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH

สำหรับการอ้างอิงดู:

https://docs.docker.com/engine/reference/commandline/cp/


47
มีความแตกต่างกันมากระหว่างการติดตั้งไดรฟ์และคัดลอกไฟล์ไปและกลับจากภาชนะที่เป็น ...
จูลส์

31
อย่างไรก็ตามมันช่วยฉันได้ ฉันไม่ทราบคำสั่ง 'docker cp' และพยายามทำสิ่งนี้ให้สำเร็จ - คัดลอกไฟล์จากการเรียกใช้ container ไปยังโฮสต์
Ivan

3
มันไม่ใช่การเมานต์ แต่มันมีประโยชน์ที่จะนำไฟล์กลับมาและเป็นฟองระหว่างคอนเทนเนอร์และโลคัลโฮสต์
linehrr

แม้ว่าวิธีนี้จะช่วยแก้ปัญหาการทำซ้ำเนื้อหาของคอนเทนเนอร์ในตัวเครื่อง แต่ก็ไม่ได้ใกล้เคียงกับการติดตั้งไดรฟ์และไม่ควรคิดว่าเป็นทางเลือก กล่าวคือการจำลองแบบจะต้องได้รับการจัดการโดยผู้ใช้และขณะนี้ข้อมูลมีอยู่ในสองแห่ง
เซบาสเตียน Gaweda

1
ฉันไม่เข้าใจว่าทำไมมีการโหวตมากนักนี่เป็นคำตอบที่ผิดมากสำหรับคำถามที่ถาม
João Matos

33

ฉันเมานท์/home/<user-name>โฟลเดอร์ของโฮสต์ของฉันไปยัง/mntโฟลเดอร์ของคอนเทนเนอร์ (ไม่ได้ทำงาน) ที่มีอยู่เรียบร้อยแล้ว คุณสามารถทำได้ด้วยวิธีต่อไปนี้:

  1. ไฟล์การกำหนดค่าแบบเปิดที่สอดคล้องกับคอนเทนเนอร์ที่หยุดทำงานซึ่งสามารถดูได้ที่/var/lib/docker/containers/99d...1fb/config.v2.json(อาจเป็นconfig.jsonสำหรับนักเทียบท่ารุ่นเก่ากว่า)

  2. ค้นหาMountPointsส่วนที่ว่างเปล่าในกรณีของฉัน: "MountPoints":{}. ถัดไปแทนที่เนื้อหาด้วยสิ่งนี้ (คุณสามารถคัดลอกเนื้อหาที่เหมาะสมจากภาชนะอื่นด้วยการตั้งค่าที่เหมาะสม):

"MountPoints":{"/mnt":{"Source":"/home/<user-name>","Destination":"/mnt","RW":true,"Name":"","Driver":"","Type":"bind","Propagation":"rprivate","Spec":{"Type":"bind","Source":"/home/<user-name>","Target":"/mnt"},"SkipMountpointCreation":false}}

หรือรูปแบบเดียวกัน:

  "MountPoints": {
    "/mnt": {
      "Source": "/home/<user-name>",
      "Destination": "/mnt",
      "RW": true,
      "Name": "",
      "Driver": "",
      "Type": "bind",
      "Propagation": "rprivate",
      "Spec": {
        "Type": "bind",
        "Source": "/home/<user-name>",
        "Target": "/mnt"
      },
      "SkipMountpointCreation": false
    }
  }
  1. รีสตาร์ทเซอร์วิส docker: service docker restart

สิ่งนี้ใช้ได้กับฉันกับ Ubuntu 18.04.1 และ Docker 18.09.0


3
ขอบคุณสำหรับคำตอบ. ขั้นตอนที่ 3 เป็นสิ่งสำคัญ ฉันยังจะเพิ่มที่ดีกว่าที่จะหยุดภาชนะนักเทียบท่าก่อนที่จะทำการเขียน
buzypi

7
นี่คือคำตอบที่ดีที่สุดเพราะมันเก็บรักษาภาชนะที่มีอยู่ทั้งหมด นี่คือสิ่งที่ฉันทำ: 1. หยุดเอ็นจิ้นนักเทียบท่า: systemctl stop docker.service2. แก้ไขconfig.v2.json: vim <(jq . /var/lib/docker/containers/<container-ID>/config.v2.json)3. บันทึกการอัพเดตไปยังไฟล์: :w config.v2.json4. ออกเป็นกลุ่ม: :q!5. อัปเดตไฟล์ที่มีอยู่: jq -c . config.v2.json > /var/lib/docker/containers/<container-ID>/config.v2.json6. เริ่มเอ็นจิ้นนักเทียบท่า: systemctl start docker.service7. เริ่มคอนเทนเนอร์หากจำเป็น : docker start <container-name/ID>8. เพลิดเพลินกับ :-)
การควบคุม Android

2
ขั้นตอนที่สำคัญservice docker restartคือ ฉันพยายามdocker restart <container>แล้วการกำหนดค่าใหม่จะไม่รับและมันก็ถูกเขียนทับโดยการกำหนดค่าเก่า
KFL

1
นอกจากนี้ยังjqจะช่วยพิมพ์ JSON ที่สวยดังนั้นมนุษย์จึงสามารถแก้ไขได้:cat config.v2.json | jq . > config.json
KFL

14

Jérôme Petazzoniมีโพสต์บล็อกที่น่าสนใจเกี่ยวกับวิธีแนบวอลลุ่มไปยังที่เก็บในขณะที่มันกำลังทำงานอยู่ นี่ไม่ใช่สิ่งที่สร้างไว้ใน Docker นอกกรอบ แต่เป็นไปได้ที่จะทำให้สำเร็จ

ในขณะที่เขายังชี้ให้เห็น

สิ่งนี้จะไม่ทำงานกับระบบไฟล์ที่ไม่ได้ใช้อุปกรณ์บล็อก

จะใช้งานได้หาก / proc / mounts แสดงรายการโหนดอุปกรณ์บล็อกอย่างถูกต้อง (ซึ่งตามที่เราเห็นด้านบนไม่จำเป็นต้องเป็นจริง)

นอกจากนี้ฉันทดสอบสิ่งนี้ในสภาพแวดล้อมท้องถิ่นของฉันเท่านั้น ฉันไม่ได้ลองอินสแตนซ์บนคลาวด์หรืออะไรทำนองนั้น

YMMV


8

น่าเสียดายที่ตัวเลือกสวิตช์เพื่อต่อเชื่อมวอลุ่มพบได้ในrunคำสั่งเท่านั้น

docker run --help

-v, --volume list Bind mount a volume (default [])

มีวิธีที่คุณสามารถหลีกเลี่ยงปัญหานี้ได้ดังนั้นคุณจึงไม่ต้องติดตั้งแอปพลิเคชันที่คุณได้ตั้งค่าไว้ในคอนเทนเนอร์แล้ว

  1. ส่งออกคอนเทนเนอร์ของคุณ docker container export -o ./myimage.docker mycontainer
  2. นำเข้าเป็นรูปภาพ docker import ./myimage.docker myimage
  3. แล้วก็ docker run -i -t -v /somedir --name mycontainer myimage /bin/bash

1
FYI - docker containerไม่ใช่คำสั่งที่ถูกต้องใน 1.11.2 (ซึ่งเป็นรุ่นล่าสุดที่รองรับโดย Synology เมื่อมีการเขียนนี้) ฉันไม่พบเอกสารใด ๆ ที่บอกว่าเมื่อถูกเพิ่มเข้ามา docker export -o ./myimage.docker mycontainerในกรณีนี้คำสั่งแรกคือ
Chris R. Donnelly

2

หมายเหตุสำหรับการใช้คอนเทนเนอร์ Docker Windows หลังจากที่ฉันต้องมองปัญหานี้เป็นเวลานาน!

Condiditions:

  • Windows 10
  • Docker Desktop (เวอร์ชั่นล่าสุด)
  • ใช้ Docker Windows Container สำหรับรูปภาพ microsoft / mssql-server-windows-developer

ปัญหา:

  • ฉันต้องการติดตั้งพจนานุกรมโฮสต์ลงในคอนเทนเนอร์ windows ของฉัน

วิธีแก้ปัญหาเป็น discripted บางส่วนที่นี่:

  • สร้างคอนเทนเนอร์นักเทียบท่า

docker run -d -p 1433:1433 -e sa_password=<STRONG_PASSWORD> -e ACCEPT_EULA=Y microsoft/mssql-server-windows-developer

  • ไปที่เชลล์คำสั่งในคอนเทนเนอร์

docker exec -it <CONTAINERID> cmd.exe

  • สร้าง DIR

mkdir DirForMount

  • หยุดภาชนะ

docker container stop <CONTAINERID>

  • กระทำคอนเทนเนอร์

docker commit <CONTAINERID> <NEWIMAGENAME>

  • ลบคอนเทนเนอร์เก่า

docker container rm <CONTAINERID>

  • สร้างคอนเทนเนอร์ใหม่ด้วยอิมเมจใหม่และการติดตั้งระดับเสียง

docker run -d -p 1433:1433 -e sa_password=<STRONG_PASSWORD> -e ACCEPT_EULA=Y -v C:\DirToMount:C:\DirForMount <NEWIMAGENAME>

หลังจากนี้ฉันแก้ไขปัญหานี้บนคอนเทนเนอร์ของ windows docker


-3

วิธีที่ดีที่สุดคือการคัดลอกไฟล์และโฟลเดอร์ทั้งหมดในไดเรกทอรีในระบบไฟล์ของคุณโดย: docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH

SRC_PATHอยู่บนคอนเทนเนอร์ DEST_PATHอยู่บน localhost

จากนั้นจึงdocker-compose downแนบโวลุ่มไปที่เดียวกันDEST_PATHและเรียกใช้คอนเทนเนอร์ Docker โดยใช้docker-compose up -d

เพิ่มระดับเสียงโดยทำตามใน docker-compose.yml

volumes:
 - DEST_PATH:SRC_PATH

มีตัวเลือกอื่นที่ดีกว่าด้านบน
MrR

แท้จริงแล้วมีตัวเลือกที่ดีกว่าอยู่ด้านบนและการคัดลอกไฟล์ไปรอบ ๆ ไม่ได้ทำการติดตั้ง นอกจากนี้นิยาม "โวลุ่ม" ที่กำหนดสำหรับตัวเลือกนักเทียบท่าคือวิธีอื่น: วอลุ่ม: - HOST_PATH: CONTAINER_PATH
Guillaume S.
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.