一、Docker概述
- Docker是一個開源的應用引擎,基於go語言開發並遵循apache2.0協議開源。
- Docker是在linux容器里運行應用的開源工具,是一種輕量級的虛擬機。
- Docker的容器技術可以在一台主機上輕松的為任何應用創建一個輕量級的、可移植的、自給自足的容器‘
Docker的Logo設計為藍色鯨魚,拖着許多集裝箱
鯨魚可看作為宿主機,集裝箱可理解為相互隔離的容器,每個集裝箱中都包含自己的應用程序
1.Docker的設計宗旨:
Build,Ship and Run Any App,Anywhere,
即通過對應用組件的封裝、發布、部署、運行等生命周期的管理,達到應用組件級別的“一次封裝,到處運行”的目的。這里的組件,既可以是一個應用,也可以是一套服務,甚至是一個完整的操作系統。
2.容器化越來越受歡迎,因為容器是:
- 靈活:即使是最復雜的應用也可以集裝箱化。
- 輕量級:容器利用並共享主機內核。
- 可互換:可以即時部署更新和升級。
- 便攜式:可以在本地構建,部署到雲,並在任何地方運行。
- 可擴展:可以增加並自動分發容器副本。
- 可堆疊:可以垂直和即時堆疊服務。
- 容器是在linux上本機運行,並與其他容器共享主機的內核,它運行的是一個獨立的進程,不占用其他任何可執行文件的內存,非常輕量
- 虛擬機運行的是一個完成的操作系統,通過虛擬機管理程序對主機資源進行虛擬訪問,相比之下需要的資源更多
3.Docker與虛擬機的區別:
特性 Docker容器 虛擬機 啟動速度 秒級 分鍾級 計算能力 損耗幾乎無損耗 50%左右 性能 接近原生 弱於 系統支持量(單機) 上千個 幾十個 隔離性 資源隔離/限制 完全隔離
4.容器在內核中支持2種重要技術:
docker本質就是宿主機的一個進程,docker是通過namespace實現資源隔離,通過cgroup實現資源限制,通過寫時復制技術(copy-on-write)實現了高效的文件操作(類似虛擬機的磁盤比如分配500g並不是實際占用物理磁盤500g)
二.Docker核心概念
- 鏡像
Docker的鏡像是創建容器的基礎,類似虛擬機的快照,可以理解為一個面向 Docker 容器引擎的只讀模板
通過鏡像啟動一個容器,一個鏡像是一個可執行的包,其中包括運行應用程序所需要的所有內容包含代碼,運行時間,庫、環境變量、和配置文件
- 容器
Docker的容器是從鏡像創建的運行實例,它可以被啟動、停止和刪除。所創建的每一個容器都是相互隔離、互不可見,以保證平台的安全性
可以把容器看做是要給簡易版的linux環境(包括root用戶權限、鏡像空間、用戶空間和網絡空間等)和運行在其中的應用程序。
- 倉庫
Docker倉庫是用來集中保存鏡像的地方,當創建了自己的鏡像之后,可以使用push命令將它上傳到公有倉庫(Public)或者私有倉庫(Private)。當下次要在另外一台機器上使用這個鏡像時,只需從倉庫獲取
Docker 的鏡像、容器、日志等內容全部都默認存儲在 /var/lib/docker 目錄下。
三.安裝 Docker
目前 Docker 只能支持 64 位系統。 systemctl stop firewalld.service setenforce 0 #安裝依賴包 yum install -y yum-utils device-mapper-persistent-data lvm2 -------------------------------------------------------------------------------------------- yum-utils:提供了 yum-config-manager 工具。 device mapper: 是Linux內核中支持邏輯卷管理的通用設備映射機制,它為實現用於存儲資源管理的塊設備驅動提供了一個高度模塊化的內核架構。 device mapper存儲驅動程序需要 device-mapper-persistent-data 和 lvm2。 -------------------------------------------------------------------------------------------- #設置阿里雲鏡像源 yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo #安裝 Docker-CE並設置為開機自動啟動 yum install -y docker-ce systemctl start docker.service systemctl enable docker.service #查看 docker 版本信息 docker version
注:使用在線源安裝
四.Docker 鏡像操作
#搜索鏡像 格式:docker search 關鍵字 docker search nginx #獲取鏡像 格式:docker pull 倉庫名稱[:標簽] #如果下載鏡像時不指定標簽,則默認會下載倉庫中最新版本的鏡像,即選擇標簽為 latest 標簽。 docker pull nginx #鏡像加速下載 瀏覽器訪問 https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors 獲取鏡像加速器配置 mkdir -p /etc/docker tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://6ijb8ubo.mirror.aliyuncs.com"] } EOF systemctl daemon-reload systemctl restart docker #查看鏡像信息 鏡像下載后存放在 /var/lib/docker #查看下載的鏡像文件信息 cat /var/lib/docker/image/overlay2/repositories.json #查看下載到本地的所有鏡像 docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest ae2feff98a0c 9 days ago 133MB -------------------------------------------------------------------------------------------- REPOSITORY:鏡像屬於的倉庫; TAG:鏡像的標簽信息,標記同一個倉庫中的不同鏡像; IMAGE ID:鏡像的唯一ID 號,唯一標識一個鏡像; CREATED:鏡像創建時間; VIRTUAL SIZE:鏡像大小; -------------------------------------------------------------------------------------------- #根據鏡像的唯一標識 ID 號,獲取鏡像詳細信息 格式:docker inspect 鏡像ID號 docker inspect ae2feff98a0c #為本地的鏡像添加新的標簽 格式:docker tag 名稱:[標簽] 新名稱:[新標簽] docker tag nginx:latest nginx:web docker images | grep nginx #刪除鏡像 格式: docker rmi 倉庫名稱:標簽 #當一個鏡像有多個標簽時,只是刪除其中指定的標簽 或者 docker rmi 鏡像ID號 #會徹底刪除該鏡像 注意:如果該鏡像已經被容器使用,正確的做法是先刪除依賴該鏡像的所有容器,再去刪除鏡像。 docker rmi nginx:web #存出鏡像:將鏡像保存成為本地文件 格式:docker save -o 存儲文件名 存儲的鏡像 docker save -o nginx nginx:latest #存出鏡像命名為nginx存在當前目錄下 ls -lh #載入鏡像:將鏡像文件導入到鏡像庫中 格式: docker load < 存出的文件 或者 docker load -i 存出的文件 docker load < nginx #上傳鏡像 默認上傳到 docker Hub 官方公共倉庫,需要注冊使用公共倉庫的賬號。https://hub.docker.com 可以使用 docker login 命令來輸入用戶名、密碼和郵箱來完成注冊和登錄。 在上傳鏡像之前,還需要先對本地鏡像添加新的標簽,然后再使用 docker push 命令進行上傳。 docker tag nginx:latest nginx:web #添加新的標簽 docker login #登錄公共倉庫 Username: password: docker push wl/nginx:web #上傳鏡像
注:此步驟 往往也是排查鏡像問題的良方
rmi后面加鏡像ID號 阿靜徹底刪除該鏡像
五.Docker 容器操作
#容器創建:就是將鏡像加載到容器的過程。 新創建的容器默認處於停止狀態,不運行任何程序,需要在其中發起一個進程來啟動容器。 格式:docker create [選項] 鏡像 常用選項: -i:讓容器的輸入保持打開 -t:讓 Docker 分配一個偽終端 docker create -it nginx:latest /bin/bash #查看容器的運行狀態 docker ps -a #-a 選項可以顯示所有的容器 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8b0a7be0ff58 nginx:latest "/docker-entrypoint.…" 57 seconds ago Created inspiring_swanson 容器的ID號 加載的鏡像 運行的程序 創建時間 當前的狀態 端口映射 名稱 #啟動容器 格式:docker start 容器的ID/名稱 docker start 8b0a7be0ff58 docker ps -a #創建並啟動容器 可以直接執行 docker run 命令, 等同於先執行 docker create 命令,再執行 docker start 命令。 注意:容器是一個與其中運行的 shell 命令共存亡的終端,命令運行容器運行, 命令結束容器退出。 當利用 docker run 來創建容器時, Docker 在后台的標准運行過程是: (1)檢查本地是否存在指定的鏡像。當鏡像不存在時,會從公有倉庫下載; (2)利用鏡像創建並啟動一個容器; (3)分配一個文件系統給容器,在只讀的鏡像層外面掛載一層可讀寫層; (4)從宿主主機配置的網橋接口中橋接一個虛擬機接口到容器中; (5)分配一個地址池中的 IP 地址給容器; (6)執行用戶指定的應用程序,執行完畢后容器被終止運行。 docker run centos:7 /usr/bin/bash -c ls / docker ps -a #會發現創建了一個新容器並啟動執行一條 shell 命令,之后就停止了 #在后台持續運行 docker run 創建的容器 需要在 docker run 命令之后添加 -d 選項讓 Docker 容器以守護形式在后台運行。並且容器所運行的程序不能結束。 docker run -d centos:7 /usr/bin/bash -c "while true;do echo hello;done" docker ps -a #可以看出容器始終處於 UP,運行狀態 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2592d3fad0fb centos:7 "/usr/bin/bash -c 'w…" 2 seconds ago Up 2 seconds peaceful_chatelet docker run -itd --name test1 centos:7 /bin/bash #終止容器運行 格式:docker stop 容器的ID/名稱 docker stop 2592d3fad0fb docker ps -a #容器的進入 需要進入容器進行命令操作時,可以使用 docker exec 命令進入運行着的容器。 格式:docker exec -it 容器ID/名稱 /bin/bash -i 選項表示讓容器的輸入保持打開; -t 選項表示讓 Docker 分配一個偽終端。 docker start 2592d3fad0fb #進入容器前,確保容器正在運行 docker exec -it 2592d3fad0fb /bin/bash ls exit #退出容器后,容器仍在運行 docker ps -a #容器的導出與導入 用戶可以將任何一個 Docker 容器從一台機器遷移到另一台機器。在遷移過程中,可以使用docker export 命令將已經創建好的容器導出為文件,無論這個容器是處於運行狀態還是停止狀態均可導出。可將導出文件傳輸到其他機器,通過相應的導入命令實現容器的遷移。 #導出格式:docker export 容器ID/名稱 > 文件名 docker export 2592d3fad0fb > centos7tar #導入格式:cat 文件名 | docker import – 鏡像名稱:標簽 cat centos7tar | docker import - centos7:test #導入后會生成鏡像,但不會創建容器 #刪除容器 格式:docker rm [-f] 容器ID/名稱 docker stop 2592d3fad0fb docker rm 2592d3fad0fb #刪除已經終止狀態的容器 docker rm -f 2592d3fad0fb #強制刪除正在運行的容器 docker ps -a | awk 'NR>=2{print "docker stop "$1}' | bash #批量停止容器 docker ps -a | awk 'NR>=2{print "docker rm "$1}' | bash #批量刪除所有容器 docker images | awk 'NR>=2{print "docker rmi "$3}' | bash #批量刪除鏡像
六.Docker 網絡
1.Docker網絡的實現原理
- Docker使用Linux橋接,在宿主機虛擬一個Docker容器網橋(docker0),Docker啟動一個容器時會根據Docker網橋的網段分配給容器一個IP地址,稱為Container-IP,同時Docker網橋是每個容器的默認網關。因為在同一宿主機內的容器都接入同一個網橋,這樣容器之間就能夠通過容器的 Container-IP 直接通信。
- Docker網橋是宿主機虛擬出來的,並不是真實存在的網絡設備,外部網絡是無法尋址到的,這也意味着外部網絡無法直接通過 Container-IP 訪問到容器。如果容器希望外部訪問能夠訪問到,可以通過映射容器端口到宿主主機(端口映射),即 docker run 創建容器時候通過 -p 或 -P 參數來啟用,訪問容器的時候就通過[宿主機IP]:[容器端口]訪問容器。
docker run -d --name test1 -P nginx #隨機映射端口( 從32768開始) docker run -d --name test2 -p 43000:80 nginx #指定映射端口 docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 9d3c04f57a68 nginx "/docker-entrypoin...." 4 seconds ago Up 3 seconds 0.0.0.0: 43000->80/tcp test2 b04895f870e5 nginx " /docker-entrypoi..." 17 seconds ago Up 15 seconds 0.0.0.0: 49170->80/ tcp test1 瀏覽器訪問: http://192.168.80.10;43000 、 http://192.168.80.10:49170
2.Docker 的網絡模式
●Host:容器將不會虛擬出自己的網卡,配置自己的IP等,而是使用宿主機的IP和端口。 ●Container:創建的容器不會創建自己的網卡,配置自己的IP,而是和一個指定的容器共享IP、端口范圍。 ●None:該模式關閉了容器的網絡功能。 ●Bridge:默認為該模式,此模式會為每一個容器分配、設置IP等,並將容器連接到一個docker0虛擬網橋,通過docker0網橋以及iptables nat 表配置與宿主機通信。 ●自定義網絡
Host:
Container:
Bridge:
#使用docker run創建Docker容器時,可以用 --net 或 --network 選項指定容器的網絡模式 ●host模式:使用 --net=host 指定。 ●none模式:使用 --net=none 指定。 ●container模式:使用 --net=container:NAME_or_ID 指定。 ●bridge模式:使用 --net=bridge 指定,默認設置,可省略。
安裝Docker時,它會自動創建三個網絡,bridge(創建容器默認連接到此網絡)、 none 、host
docker network ls #查看docker網絡列表 NETWORK ID NAME DRIVER SCOPE 2b4359d229c6 bridge bridge local 0fa580365d39 host host local cc13aa84a223 none null local
3.網絡模式詳解
1.host模式 相當於Vmware中的橋接模式,與宿主機在同一個網絡中,但沒有獨立IP地址。 Docker使用了Linux的Namespaces技術來進行資源隔離,如PID Namespace隔離進程,Mount Namespace隔離文件系統,Network Namespace隔離網絡等。 一個Network Namespace提供了一份獨立的網絡環境,包括網卡、路由、iptable規則等都與其他的Network Namespace隔離。 一個Docker容器一般會分配一個獨立的Network Namespace。 但如果啟動容器的時候使用host模式,那么這個容器將不會獲得一個獨立的Network Namespace, 而是和宿主機共用一個Network Namespace。容器將不會虛擬出自己的網卡、配置自己的IP等,而是使用宿主機的IP和端口。 2.container模式 在理解了host模式后,這個模式也就好理解了。這個模式指定新創建的容器和已經存在的一個容器共享一個Network Namespace,而不是和宿主機共享。新創建的容器不會創建自己的網卡,配置自己的IP,而是和一個指定的容器共享IP、端口范圍等。同樣,兩個容器除了網絡方面,其他的如文件系統、進程列表等還是隔離的。兩個容器的進程可以通過lo網卡設備通信。 docker run -itd --name test1 centos:7 /bin/bash #--name 選項可以給容器創建一個友好的自定義名稱 docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 3ed82355f811 centos:7 "/bin/bash" 5 days ago Up 6 hours test1 docker inspect -f '{{.State.Pid}}' 3ed82355f811 #查看容器進程號 25945 ls -l /proc/25495/ns #查看容器的進程、 網絡、文件系統等命名空間編號 lrwxrwxrwx 1 root root 0 1月 7 11:29 ipc -> ipc:[4026532572] lrwxrwxrwx 1 root root 0 1月 7 11:29 mnt -> mnt:[4026532569] lrwxrwxrwx 1 root root 0 1月 7 11:27 net -> net:[4026532575] lrwxrwxrwx 1 root root 0 1月 7 11:29 pid -> pid:[4026532573] lrwxrwxrwx 1 root root 0 1月 7 12:22 user -> user:[4026531837] lrwxrwxrwx 1 root root 0 1月 7 11:29 uts -> uts:[4026532570] docker run -itd --name test2 --net=container:3ed82355f811 centos:7 /bin/bash docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ff96bc43dd27 centos:7 "/bin/bash" 48 seconds ago Up 46 seconds test2 3ed82355f811 centos:7 "/bin/bash" 58 minutes ago Up 58 minutes test1 docker inspect -f '{{.State.Pid}}' ff96bc43dd27 27123 ls -l /proc/27123/ns #查看可以發現兩個容器的 net namespace 編號相同 lrwxrwxrwx 1 root root 0 1月 7 12:27 ipc -> ipc:[4026532692] lrwxrwxrwx 1 root root 0 1月 7 12:27 mnt -> mnt:[4026532690] lrwxrwxrwx 1 root root 0 1月 7 12:27 net -> net:[4026532575] lrwxrwxrwx 1 root root 0 1月 7 12:27 pid -> pid:[4026532693] lrwxrwxrwx 1 root root 0 1月 7 12:27 user -> user:[4026531837] lrwxrwxrwx 1 root root 0 1月 7 12:27 uts -> uts:[4026532691] 3.none模式 使用none模式,Docker容器擁有自己的Network Namespace,但是,並不為Docker容器進行任何網絡配置。 也就是說,這個Docker容器沒有網卡、IP、路由等信息。這種網絡模式下容器只有lo回環網絡,沒有其他網卡。這種類型的網絡沒有辦法聯網,封閉的網絡能很好的保證容器的安全性。 4.Bridge模式 bridge模式是docker的默認網絡模式,不寫--net參數,就是bridge模式。 相當於Vmware中的 nat 模式,容器使用獨立network Namespace,並連接到docker0虛擬網卡。通過docker0網橋以及iptables nat表配置與宿主機通信,此模式會為每一個容器分配Network Namespace、設置IP等,並將一個主機上的 Docker 容器連接到一個虛擬網橋上。 (1)當Docker進程啟動時,會在主機上創建一個名為docker0的虛擬網橋,此主機上啟動的Docker容器會連接到這個虛擬網橋上。虛擬網橋的工作方式和物理交換機類似,這樣主機上的所有容器就通過交換機連在了一個二層網絡中。 (2)從docker0子網中分配一個IP給容器使用,並設置docker0的IP地址為容器的默認網關。在主機上創建一對虛擬網卡veth pair設備。veth設備總是成對出現的,它們組成了一個數據的通道,數據從一個設備進入,就會從另一個設備出來。因此,veth設備常用來連接兩個網絡設備。 (3)Docker將veth pair 設備的一端放在新創建的容器中,並命名為eth0(容器的網卡),另一端放在主機中, 以veth*這樣類似的名字命名,並將這個網絡設備加入到docker0網橋中。可以通過 brctl show 命令查看。 (4)使用 docker run -p 時,docker實際是在iptables做了DNAT規則,實現端口轉發功能。可以使用iptables -t nat -vnL 查看。 5.自定義網絡 #直接使用bridge,無法支持指定IP運行docker docker run -itd --name test1 --network bridge --ip 172.17.0.10 centos:7 /bin/bash #可以先自定義網絡,再使用指定IP運行docker docker network create --subnet=172.18.0.0/24 mynetwork docker run -itd --name test2 --net mynetwork --ip 172.18.0.10 centos:7 /bin/bash
七.資源控制
1.CPU 資源控制
cgroups,是一個非常強大的linux內核工具,他不僅可以限制被 namespace 隔離起來的資源, 還可以為資源設置權重、計算使用量、操控進程啟停等等。 所以 cgroups( Control groups) 實現了對資源的配額和度量。
2.cgroups四大功能:
- 資源限制:可以對任務使用的資源總額進行限制
- 優先級分配:通過分配的cpu時間片數量以及磁盤IO帶寬大小,實際上相當於控制了任務運行優先級
- 資源統計:可以統計系統的資源使用量,如cpu時長,內存用量等
- 任務控制:cgroup可以對任務執行掛起、恢復等操作
(1)設置CPU使用率上限 Linux 通過 CFS(Completely Fair Scheduler,完全公平調度器)來調度各個進程對 CPU 的使用。CFS 默認的調度周期是 100ms。 我們可以設置每個容器進程的調度周期,以及在這個周期內各個容器最多能使用多少 CPU 時間。 使用 --cpu-period 即可設置調度周期,使用 --cpu-quota 即可設置在每個周期內容器能使用的 CPU 時間。兩者可以配合使用。 CFS 周期的有效范圍是 1ms~1s,對應的 --cpu-period 的數值范圍是 1000~100000。 而容器的 CPU 配額必須不小於 1ms,即 --cpu-quota 的值必須 >= 1000。 docker run -itd --name test1 centos:7 /bin/bash docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 3ed82355f811 centos:7 "/bin/bash" 5 days ago Up 6 hours test1 cd /sys/fs/cgroup/cpu/docker/3ed82355f81151c4568aaa6e7bc60ba6984201c119125360924bf7dfd6eaa42b/ cat cpu.cfs_quota_us -1 cat cpu.cfs_period_us 100000 --------------------------------------------------------------------------------------------------------- #cpu.cfs_period_us:cpu分配的周期(微秒,所以文件名中用 us 表示),默認為100000。 #cpu.cfs_quota_us:表示該control group限制占用的時間(微秒),默認為-1,表示不限制。 如果設為50000,表示占用50000/100000=50%的CPU。 --------------------------------------------------------------------------------------------------------- #進行CPU壓力測試 docker exec -it 3ed82355f811 /bin/bash vim /cpu.sh #!/bin/bash i=0 while true do let i++ done chmod +x /cpu.sh ./cpu.sh exit top #可以看到這個腳本占了很多的cpu資源 #設置50%的比例分配CPU使用時間上限 docker run -itd --name test2 --cpu-quota 50000 centos:7 /bin/bash #可以重新創建一個容器並設置限額 或者 cd /sys/fs/cgroup/cpu/docker/3ed82355f81151c4568aaa6e7bc60ba6984201c119125360924bf7dfd6eaa42b/ echo 50000 > cpu.cfs_quota_us docker exec -it 3ed82355f811 /bin/bash ./cpu.sh exit top #可以看到cpu占用率接近50%,cgroups對cpu的控制起了效果 (2)設置CPU資源占用比(設置多個容器時才有效) Docker 通過--cpu-shares 指定 CPU 份額,默認值為1024,值為1024的倍數。 #創建兩個容器為 c1 和 c2,若只有這兩個容器,設置容器的權重,使得c1和c2的CPU資源占比為1/3和2/3。 docker run -itd --name c1 --cpu-shares 512 centos:7 docker run -itd --name c2 --cpu-shares 1024 centos:7 #分別進入容器,進行壓力測試 yum install -y epel-release yum install stress -y stress -c 4 #產生四個進程,每個進程都反復不停的計算隨機數的平方根 exit #查看容器運行狀態(動態更新) docker stats CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS c3ee18e65852 c2 66.50% 5.5MiB / 976.3MiB 0.56% 20.4MB / 265kB 115MB / 14.2MB 4 bb02d3b345d8 c1 32.68% 2.625MiB / 976.3MiB 0.27% 20.4MB / 325kB 191MB / 12.7MB 4 (3)設置容器綁定指定的CPU #先分配虛擬機4個CPU核數 docker run -itd --name test2 --cpuset-cpus 1,3 centos:7 /bin/bash #進入容器,進行壓力測試 yum install -y epel-release yum install stress -y stress -c 4 exit #退出容器,執行 top 命令再按 1 查看CPU使用情況。
3.對磁盤IO配額控制(blkio)的限制
--device-read-bps:限制某個設備上的讀速度bps(數據量),單位可以是kb、mb(M)或者gb。 例:docker run -itd --name test4 --device-read-bps /dev/sda:1M centos:7 /bin/bash --device-write-bps : 限制某個設備上的寫速度bps(數據量),單位可以是kb、mb(M)或者gb。 例:docker run -itd --name test5 --device-write-bps /dev/sda:1mb centos:7 /bin/bash --device-read-iops :限制讀某個設備的iops(次數) --device-write-iops :限制寫入某個設備的iops(次數) #創建容器,並限制寫速度 docker run -it --name test5 --device-write-bps /dev/sda:1mb centos:7 /bin/bash #通過dd來驗證寫速度 dd if=/dev/zero of=test.out bs=1M count=10 oflag=direct #添加oflag參數以規避掉文件系統cache 10+0 records in 10+0 records out 10485760 bytes (10 MB) copied, 10.0025 s, 1.0 MB/s