Tôi mất dữ liệu khi hết container


394

Mặc dù hướng dẫn tương tác của Docker và faq tôi mất dữ liệu khi container thoát.

Tôi đã cài đặt Docker như được mô tả ở đây: http://docs.docker.io/en/latest/installation/ubuntulinux mà không gặp vấn đề gì trên Ubuntu 13.04.

Nhưng nó mất tất cả dữ liệu khi thoát.

iman@test:~$ sudo docker version
Client version: 0.6.4 
Go version (client): go1.1.2 
Git commit (client): 2f74b1c 
Server version: 0.6.4 
Git commit (server): 2f74b1c 
Go version (server): go1.1.2 
Last stable version: 0.6.4 


iman@test:~$ sudo docker run ubuntu ping
2013/10/25 08:05:47 Unable to locate ping 
iman@test:~$ sudo docker run ubuntu apt-get install ping
Reading package lists... 
Building dependency tree... 
The following NEW packages will be installed: 
  iputils-ping 
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. 
Need to get 56.1 kB of archives. 
After this operation, 143 kB of additional disk space will be used. 
Get:1 http://archive.ubuntu.com/ubuntu/ precise/main iputils-ping amd64 3:20101006-1ubuntu1 [56.1 kB] 
debconf: delaying package configuration, since apt-utils is not installed 
Fetched 56.1 kB in 0s (195 kB/s) 
Selecting previously unselected package iputils-ping. 
(Reading database ... 7545 files and directories currently installed.) 
Unpacking iputils-ping (from .../iputils-ping_3%3a20101006-1ubuntu1_amd64.deb) ... 
Setting up iputils-ping (3:20101006-1ubuntu1) ... 
iman@test:~$ sudo docker run ubuntu ping
2013/10/25 08:06:11 Unable to locate ping 
iman@test:~$ sudo docker run ubuntu touch /home/test
iman@test:~$ sudo docker run ubuntu ls /home/test
ls: cannot access /home/test: No such file or directory 

Tôi cũng đã thử nghiệm nó với các phiên tương tác với kết quả tương tự. Tôi đã quên một cái gì đó?

EDIT: QUAN TRỌNG CHO NGƯỜI SỬ DỤNG DOCKER MỚI

Như @ mohammed-noureldin và những người khác đã nói, thực sự đây KHÔNG phải là một container thoát . Mỗi khi nó chỉ tạo ra một container mới.


10
Điều đó không thể được gọi là " thoát khỏi container ", bạn chỉ đang tạo một container mới, sử dụng từ thoát có thể gây nhầm lẫn rất nhiều (tôi cũng bối rối vì điều đó).
Mohammed Noureldin

1
@MohammedNoureldin, bạn nói đúng, thoát là không đúng, nhưng đây chính xác là những gì bạn, tôi và những người khác nghĩ. Vì vậy, đó là một từ tốt hơn trong câu hỏi, chỉnh sửa của bạn làm cho câu hỏi một câu trả lời! Những người tìm kiếm mới sẽ không tìm thấy ở đây!
iman

Ở điểm khởi đầu của tôi với Docker, tôi nghĩ rằng thực sự là do câu hỏi của BẠN, tôi thấy địa chỉ đó đơn giản là SAI. tiêu đề mới đã được xem xét và chấp nhận, tôi không hiểu tại sao một người nào đó cứ khăng khăng cho một tiêu đề sai, đó là câu hỏi của bạn và sự tuyệt vọng của bạn.
Mohammed Noureldin

3
Tôi đồng ý với @MohammedNoureldin. Sự kết hợp của tiêu đề cụ thể, ví dụ và câu trả lời được chấp nhận không giúp người đọc trong tương lai và đặc biệt là người mới bắt đầu hiểu Docker. Tôi sẽ đề nghị giữ tiêu đề và câu hỏi ban đầu, vì những người mới bắt đầu chắc chắn sẽ tìm kiếm một cái gì đó như thế này. Nhưng, tại sao bạn không thêm một cái gì đó mô tả quan niệm sai lầm của bạn tại thời điểm bạn viết bài đăng. Nó sẽ giúp làm cho mọi thứ rõ ràng. Đây là văn hóa của chúng tôi ở đây tại SO ... phải không? :-)
tgogos

2
Tôi gặp vấn đề này ... mỗi khi bạn thoát ra, bạn phải khởi động container của mình không chạy nó ... chạy một hình ảnh agane tạo một container mới, điều này sẽ giúp docker khởi động <container id> docker đính kèm <container id>
fHReh

Câu trả lời:


399

Bạn cần phải cam kết những thay đổi bạn thực hiện với container và sau đó chạy nó. Thử cái này:

sudo docker pull ubuntu

sudo docker run ubuntu apt-get install -y ping

Sau đó lấy id container bằng lệnh này:

sudo docker ps -l

Cam kết thay đổi đối với container:

sudo docker commit <container_id> iman/ping 

Sau đó chạy container:

sudo docker run iman/ping ping www.google.com

Điều này nên làm việc.


9
Vì vậy, tôi nên sử dụng cam kết sau mỗi lần chạy để bảo toàn dữ liệu.
iman

5
Chỉ nên sử dụng cam kết khi bạn thực hiện THAY ĐỔI trong vùng chứa (như cài đặt công cụ hoặc dữ liệu mới) để những thay đổi đó được lưu và lần sau khi bạn chạy một vùng chứa mới từ Hình ảnh đó, nó sẽ bắt đầu từ điểm lưu cuối cùng hoặc cam kết, bảo quản dữ liệu của bạn.
Unferth

7
@Unferth nếu tôi muốn tiếp tục cam kết thay đổi thì sao? Cho đến nay nó tạo ra nhiều hình ảnh với <none>. Làm cách nào để tiếp tục gắn cam kết lên trên hình ảnh hiện tại?
Marconi

62
Cam kết thay đổi liên tục không phải là "cách docker". Sử dụng DOCKERFILE.
dùng2105103

23
Làm thế nào bạn sẽ cam kết từ trong container? Hãy xem xét kịch bản sau đây: 1) Tôi đang chạy container như thế này: docker run -i -t myimage / bin / bash 2) Tôi thực hiện một số thay đổi 3) Tôi không thể cam kết từ trong container, vì vậy khi tôi thoát khỏi container, tôi sẽ mất tất cả dữ liệu của tôi mà không có cơ hội thực hiện các thay đổi trước đây của tôi
qgicup

374

Khi bạn sử dụng docker runđể bắt đầu một container, nó thực sự tạo ra một container mới dựa trên hình ảnh bạn đã chỉ định.

Bên cạnh các câu trả lời hữu ích khác ở đây, lưu ý rằng bạn có thể khởi động lại một container hiện có sau khi nó thoát và các thay đổi của bạn vẫn còn đó.

docker start f357e2faab77 # restart it in the background
docker attach f357e2faab77 # reattach the terminal & stdin

88
docker pscho thấy bạn chỉ chạy container docker. docker ps -acũng cho bạn thấy những cái đã thoát - và bạn có thể tiếp tục chạy. Một cam kết chỉ cần thiết sau mỗi lần chạy nếu bạn muốn tạo một ảnh chụp nhanh ở đó để sử dụng trong tương lai, nếu không, thùng chứa sẽ dính xung quanh để bạn tiếp tục sử dụng.
1278519

2
Xin hỏi, vì vậy nếu tôi tải xuống một jenkinsdocker máy chủ và tôi chạy nó trên máy chủ ci của tôi và nó chạy một số công việc tôi có và kết quả là máy chủ jenkins ghi vào đĩa một số nhật ký. Bây giờ nếu máy chủ của tôi (được lưu trữ docker của tôi) được khởi động lại và tôi bắt đầu lại docker jenkins của tôi thì có nghĩa là tôi đã mất tất cả các tệp nhật ký? nếu đó là như vậy, làm thế nào tôi có thể sử dụng jenkinsdocker chẳng hạn để dễ dàng cài đặt jenkins trên CI?
Jas

2
@Jas Nếu bạn dính vào cùng một container và không tạo cái mới, không có vấn đề gì. Docker ngày nay có các chính sách khởi động lại, vì vậy bạn có thể định cấu hình nó để khởi động lại cùng một thùng chứa khi khởi động lại máy. Tôi cũng sẽ khuyên bạn nên đặt ngôi nhà của bạn vào một quyển sách để có thể truy cập nó từ bên ngoài (bản sao lưu, v.v.).
ZeissS

7
Đây là một cách hữu ích để sao chép các tệp ra khỏi vùng chứa khi bạn thoát:docker cp $(docker ps -alq):/path/to/file .
Josh Habdas

3
bạn cũng có thể bắt đầu và đính kèm một container theo tên của nó. (ví dụ docker run -it --name my_debian debianvà sau docker start my_debian && docker attach my_debian)
Johnny Willer

128

Có những cách sau để duy trì dữ liệu container:

  1. Khối lượng Docker

  2. Docker cam kết

    a) tạo vùng chứa từ hình ảnh Ubuntu và chạy thiết bị đầu cuối bash.

       $ docker run -i -t ubuntu:14.04 /bin/bash
    

    b) Bên trong thiết bị đầu cuối cài đặt curl

       # apt-get update
       # apt-get install curl
    

    c) Thoát khỏi thiết bị đầu cuối container

       # exit
    

    d) Ghi lại id container của bạn bằng cách thực hiện lệnh sau:

       $ docker ps -a
    

    e) lưu container như hình ảnh mới

       $ docker commit <container_id> new_image_name:tag_name(optional)
    

    f) xác minh rằng bạn có thể thấy hình ảnh mới của mình với cài đặt curl.

       $ docker images           
    
       $ docker run -it new_image_name:tag_name bash
          # which curl
            /usr/bin/curl
    

Có cần thiết exittrước đây docker commitkhông? Cảm ơn.
Abhishek Anand

2
@AbhishekAnand có, bởi vì với docker runlệnh bạn chạy bash trong container và bạn ở lại đó do các tùy chọn -i-t(tương tác với TTY). Tuy nhiên, Docker chạy trên máy của bạn, bên ngoài thùng chứa, vì vậy sau khi thực hiện các thay đổi cần thiết cho thùng chứa từ bên trong, để quay lại vỏ hệ thống của bạn, bạn phải exit(hoặc Ctrl + D) vỏ của bộ chứa. Cũng lưu ý #$trong câu trả lời, chỉ ra các shell khác nhau mà các lệnh được ghi vào.
Erik

Câu hỏi nhanh: Nếu tôi không cam kết, tôi sẽ mất dữ liệu. Rõ ràng. Nhưng khi tôi thay đổi cấu hình nginx, tại sao nó vẫn được cập nhật? (không cần phải cam kết) @Erik
grep

@grep nếu bạn có một MWE rõ ràng và có thể tái tạo, vui lòng đặt câu hỏi mới về nó, nếu chưa có câu hỏi nào về trường hợp sử dụng cụ thể này.
Erik

3. docker stoptheo sau docker start.
carillonator

59

Ngoài câu trả lời của Unferth , bạn nên tạo Dockerfile .

Trong một thư mục trống, tạo một tệp có tên "Dockerfile" với các nội dung sau.

FROM ubuntu
RUN apt-get install ping
ENTRYPOINT ["ping"]

Tạo một hình ảnh bằng cách sử dụng Dockerfile . Chúng ta hãy sử dụng một thẻ để chúng ta không cần nhớ số hình ảnh thập lục phân.

$ docker build -t iman/ping .

Và sau đó chạy hình ảnh trong một container.

$ docker run iman/ping stackoverflow.com

1
Không bao giờ phải làm thủ công nhiều lần là chính xác điểm của docker. Tạo một dockerfile, cam kết và tải lên hình ảnh kết quả. Kéo hình ảnh nói về phía trước.
Brandon Bertelsen

11

Tôi đã có một câu trả lời đơn giản hơn nhiều cho câu hỏi của bạn, hãy chạy hai lệnh sau

sudo docker run -t -d ubuntu --name mycontainername /bin/bash
sudo docker ps -a

lệnh ps -a ở trên trả về một danh sách tất cả các container. Lấy tên của thùng chứa tham chiếu tên hình ảnh - 'ubfox'. docker auto tạo tên cho các container chẳng hạn - 'lightlyxuyzx', đó là nếu bạn không sử dụng tùy chọn --name.

Các tùy chọn -t và -d rất quan trọng, thùng chứa đã tạo được tách ra và có thể được gắn lại như được đưa ra dưới đây với tùy chọn -t.

Với tùy chọn --name, bạn có thể đặt tên cho thùng chứa của mình trong trường hợp của tôi 'mycontainername'.

sudo docker exec -ti mycontainername bash

và lệnh trên giúp bạn đăng nhập vào container bằng bash shell. Từ thời điểm này, mọi thay đổi bạn thực hiện trong vùng chứa sẽ được lưu tự động bởi docker. Ví dụ: apt-get install curlbên trong container Bạn có thể thoát khỏi container mà không gặp sự cố nào, docker auto lưu các thay đổi.

Trong lần sử dụng tiếp theo, tất cả những gì bạn phải làm là, chạy hai lệnh này mỗi khi bạn muốn làm việc với thùng chứa này.

Lệnh Dưới đây sẽ bắt đầu container bị dừng:

sudo docker start mycontainername

sudo docker exec -ti mycontainername bash

Một ví dụ khác với các cổng và không gian chia sẻ được đưa ra dưới đây:

docker run -t -d --name mycontainername -p 5000:5000 -v ~/PROJECTS/SPACE:/PROJECTSPACE 7efe2989e877 /bin/bash

Trong trường hợp của tôi: 7efe2989e877 - là hình ảnh của một container trước đó đang chạy mà tôi thu được bằng cách sử dụng

bến tàu ps -a


4
Với Docker 18.09.2 trên Ubuntu 18.04, nó không hoạt động như hiện tại. Nó hoạt động nếu tôi đặt --nametùy chọn và trước tên hình ảnh, như thế này:docker run --name mycontainername -t -d ubuntu /bin/bash
Stéphane Gourichon


3

Đề nghị của tôi là quản lý docker, với docker compose. Thật dễ dàng để quản lý tất cả các container của docker cho dự án của bạn, bạn có thể ánh xạ các phiên bản và liên kết các container khác nhau để làm việc cùng nhau.

Các tài liệu rất đơn giản để hiểu, tốt hơn các tài liệu của docker.

Docker-Soạn tài liệu

Tốt


3

Có những câu trả lời thực sự tuyệt vời ở trên cho câu hỏi được hỏi. Có thể không cần câu trả lời khác nhưng tôi vẫn muốn đưa ra ý kiến ​​cá nhân của mình về chủ đề này bằng những từ đơn giản nhất có thể.

Dưới đây là một số điểm về container & hình ảnh sẽ giúp chúng tôi kết luận:

  • Một hình ảnh docker có thể được :
    1. tạo-từ-một-cho-container
    2. đã xóa
    3. đã sử dụng để tạo bất kỳ số lượng container nào
  • Một container docker có thể được :
    1. tạo-từ-một-hình ảnh
    2. đã bắt đầu
    3. dừng lại
    4. khởi động lại
    5. đã xóa
    6. sử dụng để tạo bất kỳ số lượng hình ảnh
  • Một lệnh chạy docker làm điều này :
    1. Tải xuống một hình ảnh hoặc sử dụng một hình ảnh lưu trữ
    2. Tạo một container mới từ nó
    3. Khởi động container
  • Khi Dockerfile được sử dụng để tạo hình ảnh :
    1. Người ta đã biết rằng hình ảnh cuối cùng sẽ được sử dụng để chạy một container docker.
    2. Sau khi ban hành lệnh xây dựng docker, docker phía sau hậu trường tạo ra một container đang chạy với hệ thống tệp cơ sở và làm theo các bước bên trong Dockerfile để cấu hình container đó theo nhu cầu của nhà phát triển.
    3. Sau khi container được cấu hình với thông số kỹ thuật của Dockerfile, nó sẽ được cam kết dưới dạng hình ảnh.
    4. Hình ảnh đã sẵn sàng để rock & roll!

Phần kết luận :

Như chúng ta có thể thấy, một container docker độc lập với hình ảnh docker.

Một container có thể được khởi động lại với điều kiện ID duy nhất của container đó [sử dụng docker ps --allđể lấy id] .

Bất kỳ hoạt động nào như tạo một thư mục mới, tạo tệp, cài đặt công cụ, v.v. đều có thể được thực hiện bên trong container khi nó đang chạy. Khi container được dừng lại, nó vẫn tồn tại tất cả các thay đổi. Container dừng và khởi động lại giống như khởi động lại hệ thống máy tính.

Một thùng chứa đã được tạo luôn có sẵn để khởi động lại nhưng khi chúng ta ra docker runlệnh, một thùng chứa mới được tạo ra từ một hình ảnh và do đó nó giống như một hệ thống máy tính mới. Những thay đổi được thực hiện bên trong container cũ - như chúng ta có thể hiểu bây giờ - không có sẵn trong container mới này.

Một lưu ý cuối cùng :

Tôi đoán bây giờ rõ ràng tại sao dữ liệu dường như bị mất nhưng nó luôn ở đó .. nhưng trong một thùng chứa [cũ] khác. Vì vậy, hãy lưu ý đến sự khác biệt trong docker start& docker runlệnh & không bao giờ bị nhầm lẫn trong chúng.


1

vấn đề tương tự (và không cách nào Dockerfile có thể khắc phục được) đã đưa tôi đến trang này.

giai đoạn 0: với tất cả, hy vọng Dockerfile có thể khắc phục nó: cho đến khi --dns và --dns-search sẽ xuất hiện trong hỗ trợ Dockerfile - không có cách nào để tích hợp tài nguyên dựa trên mạng nội bộ vào.

giai đoạn 1: sau khi xây dựng hình ảnh bằng Dockerfile (nhân tiện, đó là một trục trặc nghiêm trọng Dockerfile phải có trong thư mục hiện tại ), có một hình ảnh để triển khai mạng nội bộ dựa trên, bằng cách chạy tập lệnh chạy docker. thí dụ: docker run -d \ --dns=${DNSLOCAL} \ --dns=${DNSGLOBAL} \ --dns-search=intranet \ -t pack/bsp \ --name packbsp-cont \ bash -c " \ wget -r --no-parent http://intranet/intranet-content.tar.gz \ tar -xvf intranet-content.tar.gz \ sudo -u ${USERNAME} bash --norc"

giai đoạn 2: áp dụng tập lệnh chạy docker trong chế độ daemon cung cấp các bản ghi dns cục bộ để có khả năng tải xuống và triển khai các công cụ cục bộ.

Điểm quan trọng: tập lệnh chạy phải được kết thúc bằng một cái gì đó như /usr/bin/sudo -u ${USERNAME} bash --norcđể giữ container chạy ngay cả sau khi tập lệnh cài đặt kết thúc.

không , không thể chạy container trong chế độ tương tác cho vấn đề tự động hóa hoàn toàn vì nó sẽ vẫn ở bên trong sẽ nhắc lệnh cho đến khi nhấn CTRL-p CTRL-q .

không , nếu bash tương tác sẽ không được thực thi ở cuối tập lệnh cài đặt, bộ chứa sẽ chấm dứt ngay sau khi hoàn thành thực thi tập lệnh, mất tất cả các kết quả cài đặt.

giai đoạn 3: container vẫn đang chạy trong nền nhưng không rõ liệu container đã kết thúc quy trình cài đặt hay chưa. sử dụng khối sau để xác định kết thúc thủ tục thực thi: while ! docker container top ${CONTNAME} | grep "00[[:space:]]\{12\}bash \--norc" - do echo "." sleep 5 done tập lệnh sẽ tiếp tục chỉ sau khi cài đặt hoàn tất. và đây là thời điểm thích hợp để gọi: commit , cung cấp id container hiện tại cũng như tên hình ảnh đích (có thể giống như trong quy trình xây dựng / chạy nhưng được gắn với thẻ mục đích cài đặt cục bộ. ví dụ : docker commit containerID pack/bsp:toolchained. xem liên kết này trên làm thế nào để có được containerID thích hợp

giai đoạn 4: container đã được cập nhật với các bản cài đặt cục bộ cũng như nó đã được cam kết thành hình ảnh mới được gán (thẻ có mục đích được thêm vào). Bây giờ an toàn để dừng container chạy. thí dụ:docker stop packbsp-cont

giai đoạn 5: bất kỳ lúc nào bộ chứa có cài đặt cục bộ yêu cầu chạy, hãy khởi động nó với hình ảnh được lưu trước đó. thí dụ:docker run -d -t pack/bsp:toolchained


1

một câu trả lời tuyệt vời ở đây Làm thế nào để tiếp tục một docker được thoát ra từ kg người dùng

docker start $(docker ps -a -q --filter "status=exited")
(or in this case just docker start $(docker ps -ql) 'cos you don't want to start all of them)

docker exec -it <container-id> /bin/bash

Đó là dòng thứ hai là rất quan trọng. Vì vậy, exec được sử dụng thay cho chạy, và không phải trên một hình ảnh mà trên một container. Và bạn làm điều đó sau khi container đã được bắt đầu.


0

Không có câu trả lời nào đề cập đến điểm của sự lựa chọn thiết kế này. Tôi nghĩ rằng docker hoạt động theo cách này để ngăn chặn 2 lỗi này:

  • Khởi động lại nhiều lần
  • Lỗi một phần
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.