一、概念
镜像image:镜像是静态的,可被用户相互分享的文件,对外是一个统一的文件系统,你不能对他操作,只能pull别人的镜像或者push自己的镜像,可用来创建Docker容器。
镜像是一种文件结构。Dockerfile中的每条命令都会在文件系统中创建一个新的层次结构,文件系统在这些层次上构建起来,镜像就构建于这些联合的文件系统之上。容器container,是动态的环境,是镜像创建的运行实例,这容器装的就是我们部署的应用在运行,可被启动,停止,删除,重启,可理解为宿主机上的一个运行的进程,只不过由于docker帮我们包装了这个进程,给这个进程加一个可运行的微linux环境。
仓库(Repository):Docker中的仓库很像git的代码仓库,集中存放镜像文件的场所,保存我们的images,可以push 、pull 镜像。
Dockerfile用来构建镜像的配置文件,文件使用说明:https://yeasy.gitbook.io/docker_practice/image/dockerfile/
研究镜像与容器的关系:容器是一个动态的环境,每一层镜像中的文件属于静态内 容,然而 Dockerfile 中的 ENV、VOLUME、CMD 等内容最终都需要落实到容器的运行环境中,而这些内容均不可能直接坐落到每一层镜像所包含的文件系统内容中,那此时每一个Docker镜像还会包含 json文件记录与容器之间的关系。
因此,Docker镜像的内容主要包含两个部分:第一,镜像层文件内容;第二,镜像json文件。
二、QA大集合
1、为啥要用容器?
那么应用容器长什么样子呢,一个做好的应用容器长得就好像一个装好了一组特定应用的虚拟机一样。比如我现在想用MySQL那我就找个装好MySQL的容器,运行起来,那么我就可以使用 MySQL了。
那么我直接装个 MySQL不就好了,何必还需要这个容器这么诡异的概念?话是这么说,可是你要真装MySQL的话可能要再装一堆依赖库,根据你的操作系统平台和版本进行设置,有时候还要从源代码编译报出一堆莫名其妙的错误,可不是这么好装。而且万一你机器挂了,所有的东西都要重新来,可能还要把配置在重新弄一遍。但是有了容器,你就相当于有了一个可以运行起来的虚拟机,只要你能运行容器,MySQL的配置就全省了。而且一旦你想换台机器,直接把这个容器端起来,再放到另一个机器就好了。硬件,操作系统,运行环境什么的都不需要考虑了。
在公司中的一个很大的用途就是可以保证线下的开发环境、测试环境和线上的生产环境一致。当年在 Baidu 经常碰到这样的事情,开发把东西做好了给测试去测,一般会给一坨代码和一个介绍上线步骤的上线单。结果代码在测试机跑不起来,开发就跑来跑去看问题,一会儿啊这个配置文件忘了提交了,一会儿啊这个上线命令写错了。找到了一个 bug 提上去,开发一看,啊我怎么又忘了把这个命令写在上线单上了。类似的事情在上线的时候还会发生,变成啊你这个软件的版本和我机器上的不一样……在 Amazon 的时候,由于一个开发直接担任上述三个职位,而且有一套自动化部署的机制所以问题会少一点,但是上线的时候大家还是胆战心惊。
若果利用容器的话,那么开发直接在容器里开发,提测的时候把整个容器给测试,测好了把改动改在容器里再上线就好了。通过容器,整个开发、测试和生产环境可以保持高度的一致。
此外容器也和VM一样具有着一定的隔离性,各个容器之间的数据和内存空间相互隔离,可以保证一定的安全性。
2、那为啥不用VM?
容器相对于虚拟机的优势:
- 启动速度快,容器通常在一秒内可启动,VM通常要更久
- 资源利用率高,一台普通 PC 可以跑上千个容器,你跑上千个 VM 试试
- 性能开销小, VM 通常需要额外的 CPU 和内存来完成 OS 的功能,这一部分占据了额外的资源。
设计理念的区别如下:
三、Docker 和虚拟机的区别、设计理念
这是docker官网的图,可以看到:
虚拟化技术通过Hypervisor(虚拟机管理系统)为每个app启动一个Guest OS(客户机操作系统),也就是为每个app启动一个虚拟机
比较直观地说,vm通过Hypervisor对硬件资源进行虚拟化,而docker直接使用硬件资源,利用率上来看docker明显更具有优势。
Docker 的容器利用了 LXC,管理利用了 namespaces 来做权限的控制和隔离, cgroups 来进行资源的配置,并且还通过 aufs 来进一步提高文件系统的资源利用率。
其中的 aufs 是个很有意思的东西,是 UnionFS 的一种。他的思想和 git 有些类似,可以把对文件系统的改动当成一次 commit 一层层的叠加。这样的话多个容器之间就可以共享他们的文件系统层次,每个容器下面都是共享的文件系统层次,上面再是各自对文件系统改动的层次,这样的话极大的节省了对存储的需求,并且也能加速容器的启动。
举个简单例子。一个房子比较大,假如租户一起住,大家一起住难免有束缚感,也不太方便。那么房东把房子改造一下,房子用可拆装的墙板隔离开来,分为许多的小房间,每个人住在自己的小房间。小房间麻雀虽小,五张俱全,你可以自己布置自己的房间。每个租客在自己的"小房间"里面可以做自己的事情,从而也不会打扰到其他人。但是他们都是共享这个房子的水费,电费,网费等公共资源(每个docker容器(也就是进程)依赖的是宿主机的资源)。 聪明的你会想到, 可拆装的墙板隔音效果或安全性不够(docker容器之间的隔离性比真实虚拟机要稍微弱), 会不会有坏人打个洞偷窥? 会不会有人监听我在房间的一举一动? 可拆装的墙板肯定是不比水泥墙(虚拟机隔离性)牢固.虽说隔离性没有虚拟机那么强,但是目前为止docker还没暴露出关于这方面的问题,广泛的社区以及大厂Google等公司都在使用,所以我们还是可以放心大胆使用的。 假如有一天房东要把房子卖了,只要把可拆装的墙板移除,打扫一下,回到原样,不破坏房子原样,就可以出售房子了(在容器中安装的软件,程序等都不会污染到宿主机的环境,容器被删除也就被删除了)。
docker容器可以打包为镜像文件(类似VM虚拟机的那些快照文件),迁移的时候我们只需要在新服务器上安装docker,就能把之前打包好的镜像文件导入到docker里面,运行容器,就能实现访问,不需要重新配置环境。
四、Docker命令
4.1 基础命令
attach 进入一个运行的容器
build 从一个DockerFile构建镜像
commit 从容器创建一个镜像
cp 从容器和主机文件系统之间拷贝文件
create 创建一个容器
diff 检查容器文件系统上的更改
events 从服务器获取实时事件
exec 在正在运行的容器中运行命令
export 将容器的文件系统导出为tar存档
history 显示镜像的历史记录
images 查看镜像列表
import 从归档文件中创建镜像
info 显示系统范围的信息
inspect 返回Docker对象的低级信息
kill kill运行中的容器
load 从存档或者STDIN加载镜像
login 登陆docker镜像仓库
logout 退出docker镜像仓库
logs 获取一个容器的日志
pause 暂停一个或多个容器中的所有进程
port 查看端口映射或容器的特定映射列表
ps 查看容器列表
pull 从镜像仓库拉取镜像
push 将本地的镜像上传到镜像仓库,要先登陆到镜像仓库
rename 重命名容器
restart 重启容器
rm 删除容器
rmi 删除镜像
run 创建一个新的容器并运行一个命令
save 将指定镜像保存成 tar 归档文件
search 从Docker Hub搜索镜像
start 启动容器
stats 实时显示容器资源使用情况的统计信息
docker stats --no-stream 如果不加--no-stream参数,会实时刷新显示资源使用情况。加了,不会实时显示
stop 停止容器
tag 标记本地镜像,将其归入某一仓库
top 展示一个容器中运行的进程
unpause 恢复容器中所有的进程
update 更新容器配置
version 显示Docker的版本信息
wait 阻塞直到容器停止,然后打印退出代码
4.2例子展示
1、下载镜像
docker pull centos
2、查看已经下载的镜像
[root@bigdatafat030161 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
harbor.ppdaicorp.com/library/chatbotapi v2 e1a547ab7ef7 8 days ago 4.3 GB
harbor.ppdaicorp.com/library/chatbotapi v1 678de25a4f43 8 days ago 4.3 GB
3、运行一个镜像生成容器
docker run -d --name chatbotapi -e SIMPLE_ENV="test" -p 8000:8000 -v /etc/ppd:/etc/ppd harbor.ppdaicorp.com/library/chatbotapi:v2
4、查看运行中的容器,查看所有容器,并显示状态
[root@bigdatafat030161 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
132743c12d5d harbor.ppdaicorp.com/library/chatbotapi:v2 "/var/simple/entry..." 2 days ago Up 2 days 0.0.0.0:8000->8000/tcp chatbotapi
[root@bigdatafat030161 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
132743c12d5d harbor.ppdaicorp.com/library/chatbotapi:v2 "/var/simple/entry..." 2 days ago Up 2 days 0.0.0.0:8000->8000/tcp chatbotapi
c4a394b9aac3 harbor.ppdaicorp.com/library/chatbotapi:v2 "/var/simple/entry..." 8 days ago Exited (2) 8 days ago condescending_albattani
0bb1a017e805 harbor.ppdaicorp.com/library/chatbotapi:v1 "/var/simple/entry..." 8 days ago Exited (0) 8 days ago hungry_aryabhata
5、从DockerFile创建镜像
docker build -t myimage:v1 .
-t :指定镜像名称和标签,格式为'name:tag' .: 最后一个点代表当前目录,也可以换成其它的路径
五、构建镜像
构建Docker镜像有以下两种方法:
- 使用docker commit命令。不推荐
- 使用docker build命令和 Dockerfile 文件。推荐
5.1创建Dockerfile文件
dockerfile文件详解
https://www.cnblogs.com/jpfss/p/10947810.html
https://yeasy.gitbook.io/docker_practice/image/build
从刚才的 docker commit 的学习中,我们可以了解到,镜像的定制实际上就是定制每一层所添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么之前提及的无法重复的问题、镜像构建透明性的问题、体积的问题就都会解决。这个脚本就是 Dockerfile。
Dockerfile 是一个文本文件,其内包含了一条条的 指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
下面将介绍如何通过Dockerfile的定义文件和docker build命令来构建镜像。
Dockerfile使用基本的基于DSL语法的指令来构建一个Docker镜像,之后使用docker build命令基于该Dockerfile中的指令构建一个新的镜像。
# Version: 0.0.1
FROM ubuntu:latest
MAINTAINER Bourbon Tian "bourbon@1mcloud.com"
RUN apt-get update
RUN apt-get install -y nginx
RUN echo 'Hi, I am in your container' > /usr/share/nginx/html/index.html
EXPOSE 80
Dockerfile由一系列指令和参数组成。每条指令都必须为大写字母,切后面要跟随一个参数。Dockerfile中的指令会按照顺序从上到下执行,所以应该根据需要合理安排指令的顺序。每条指令都会创建一个新的镜像层并对镜像进行提交。Docker大体上按照如下流程执行Dockerfile中的指令。
- Docker从基础镜像运行一个容器。
- 执行第一条指令,对容器进行修改。
- 执行类似docker commit的操作,提交一个新的镜像层。
- Docker再基于刚提交的镜像运行一个新的容器。
- 执行Dockerfile中的下一条命令,直到所有指令都执行完毕。
FROM:
每个Dockerfile的第一条指令都应该是FROM。FROM指令指定一个已经存在的镜像,后续指令都是将基于该镜像进行,这个镜像被称为基础镜像(base iamge)。在这里ubuntu:latest就是作为新镜像的基础镜像。也就是说Dockerfile构建的新镜像将以ubuntu:latest操作系统为基础。在运行一个容器时,必须要指明是基于哪个基础镜像在进行构建。
RUN:
在这些命令之后,我们指定了三条RUN指令。RUN指令会在当前镜像中运行指定的命令。这里我们通过RUN指令更新了APT仓库,安装nginx包,并创建了一个index.html文件。像前面说的那样,每条RUN指令都会创建一个新的镜像层,如果该指令执行成功,就会将此镜像层提交,之后继续执行Dockerfile中的下一个指令。
默认情况下,RUN指令会在shell里使用命令包装器/bin/sh -c 来执行。如果是在一个不支持shell的平台上运行或者不希望在shell中运行(比如避免shell字符串篡改),也可以使用exec格式的RUN指令,通过一个数组的方式指定要运行的命令和传递给该命令的每个参数:
EXPOSE:
EXPOSE指令是告诉Docker该容器内的应用程序将会使用容器的指定端口。这并不意味着可以自动访问任意容器运行中服务的端口。出于安全的原因,Docker并不会自动打开该端口,而是需要你在使用docker run运行容器时来指定需要打开哪些端口。
要将 EXPOSE 和在运行时使用 -p <宿主端口>:<容器端口> 区分开来。-p,是映射宿主端口和容器端口,换句话说,就是将容器的对应端口服务公开给外界访问,而 EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会自动在宿主进行端口映射
5.2基于Dockerfile构建新镜像
执行docker build命令时,Dockerfile中的所有指令都会被执行并且提交,并且在该命令成功结束后返回一个新镜像。
# cd static_web
# docker build -t="test/static_web" .
Sending build context to Docker daemon 2.048 kB
Sending build context to Docker daemon
...
Successfully built 94728651ce15
- -t选项为新镜像设置了仓库和名称,这里仓库为test,镜像名为static_web。建议为自己的镜像设置合适的名字方便以后追踪和管理
也可以在构建镜像的过程当中为镜像设置一个标签:
# docker build -t="test/static_web:v1" .
上面命令中最后的“.”告诉Docker到当前目录中去找Dockerfile文件。也可以指定一个Git仓库地址来指定Dockerfile的位置,这里Docker假设在Git仓库的根目录下存在
docker build -t="test/static_web:v1" git@github.com:test/static_web
再回到docker build过程。可以看到构建上下文已经上传到Docker守护进程:
Sending build context to Docker daemon 2.048 kB
Sending build context to Docker daemon
之后,可以看到Dockerfile中的每条指令会被顺序执行,而作为构建过程中最终结果,返回了新镜像的ID,即94728651ce15。构建的每一步及其对应指令都会独立运行,并且在输出最终镜像ID之前,Docker会提交每步的构建结果。
5.2.1指令失败时会怎样?
假设我们将安装的软件包名字弄错,比如写成ngin,再次运行docker build:
# docker build -t="test/static_web" .
Sending build context to Docker daemon 2.048 kB
Sending build context to Docker daemon
Step 0 : FROM ubuntu:latest
---> f5bb94a8fac4
Step 1 : MAINTAINER Bourbon Tian "bourbon@1mcloud.com"
---> Using cache
---> ce64f2e75a74
Step 2 : RUN apt-get update
---> Using cache
---> e98d2c152d1d
Step 3 : RUN apt-get install -y ngin
---> Running in 2f16c5f11250
Reading package lists...
Building dependency tree...
Reading state information...
E: Unable to locate package ngin
The command '/bin/sh -c apt-get install -y ngin' returned a non-zero code: 100
这时我们需要调试一下这次失败,我们可以通过docker run命令来基于这次构建到目前为止已经成功的最后一步创建一个容器,这里它的ID是e98d2c152d1d(上面step2的结果):
# docker run -t -i e98d2c152d1d /bin/bash
root@55aee4322f77:/# apt-get install -y ngin
Reading package lists... Done
Building dependency tree
Reading state information... Done
E: Unable to locate package ngin
再次运行出错的指令apt-get install -y ngin,发现这里没有找到ngin包,我们执行安装nginx包时,包命输错了。这时退出容器使用正确的包名修改Dockerfile文件,之后再尝试进行构建。
5.2.2查看新镜像:
现在来看一下新构建的镜像,使用docker image命令,如果想深入探求镜像如何构建出来的,可以使用docker history命令看到新构建的test/static_web镜像的每一层,以及创建这些层的Dockerfile指令。
# docker images test/static_web
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
test/static_web latest 94728651ce15 20 hours ago 212.1 MB
# docker history 94728651ce15
IMAGE CREATED CREATED BY SIZE COMMENT
94728651ce15 20 hours ago /bin/sh -c #(nop) EXPOSE 80/tcp 0 B
09e999b131f4 20 hours ago /bin/sh -c echo 'Hi, I am in your container' 27 B
4af2ef04fb91 20 hours ago /bin/sh -c apt-get install -y nginx 56.52 MB
e98d2c152d1d 20 hours ago /bin/sh -c apt-get update 38.29 MB
...
5.3 从新镜像启动容器
下面基于新构建的镜像启动一个新容器,来检查之前的构建工作是否一切正常:
docker run -d -p 80 --name static_web test/static_web nginx -g "daemon off;"
- -p : 容器端口
这将在Docker宿主机上随机打开一个端口,这个端口会连接到容器中的80端口上。可以使用docker ps命令查看容器的端口分配情况 - 这里也指定了需要在容器中运行的命令:nginx -g "daemon off;"。这将以前台运行的方式启动Nginx,来作为我们的Web服务器。
# docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0b422bbcce10 test/static_web "nginx -g 'daemon of 5 seconds ago Up 5 seconds 0.0.0.0:32772->80/tcp static_web
可看到,宿主机中映射的端口,即32772。当然也可指定宿主机的端口 - p 9000:8000
项目实际的例子:
[root@bigdatafat030161 chatbotapi-master-f94211c0795c6828e06a3e7fbb751fa624b89633]# docker build -t="chatbot" .
Sending build context to Docker daemon 265.5 MB
Step 1/4 : ARG BASE
Please provide a source image with `from` prior to commit
[root@bigdatafat030161 chatbotapi-master-f94211c0795c6828e06a3e7fbb751fa624b89633]# vim
[root@bigdatafat030161 chatbotapi-master-f94211c0795c6828e06a3e7fbb751fa624b89633]# vim Dockerfile
[root@bigdatafat030161 chatbotapi-master-f94211c0795c6828e06a3e7fbb751fa624b89633]# docker build -t="chatbot" .
Sending build context to Docker daemon 265.5 MB
Step 1/3 : FROM harbor.ppdaicorp.com/library/chatbotapi:v2
---> e1a547ab7ef7
Step 2/3 : EXPOSE 8000
---> Running in 0349269dd51d
---> d4f5f001450b
Removing intermediate container 0349269dd51d
Step 3/3 : CMD uwsgi --http :8000 --chdir $PWD --module wsgi -p 2 --master --max-request=50000 --harakiri=20 --listen=100 --disable-logging --enable-threads
---> Running in e0c9d5e21b5a
---> db0336818336
Removing intermediate container e0c9d5e21b5a
Successfully built db0336818336
[root@bigdatafat030161 chatbotapi-master-f94211c0795c6828e06a3e7fbb751fa624b89633]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
chatbot latest db0336818336 17 seconds ago 4.3 GB
harbor.ppdaicorp.com/library/chatbotapi v2 e1a547ab7ef7 8 days ago 4.3 GB
harbor.ppdaicorp.com/library/chatbotapi v1 678de25a4f43 8 days ago 4.3 GB
[root@bigdatafat030161 chatbotapi-master-f94211c0795c6828e06a3e7fbb751fa624b89633]#
[root@bigdatafat030161 chatbotapi-master-f94211c0795c6828e06a3e7fbb751fa624b89633]#
[root@bigdatafat030161 chatbotapi-master-f94211c0795c6828e06a3e7fbb751fa624b89633]#
[root@bigdatafat030161 chatbotapi-master-f94211c0795c6828e06a3e7fbb751fa624b89633]#
[root@bigdatafat030161 chatbotapi-master-f94211c0795c6828e06a3e7fbb751fa624b89633]# docker run -d --name chatbotapi4 -e SIMPLE_ENV="test" -p 8001:8000 -v /etc/ppd:/etc/ppd chatbot 122af44829cdeb2fdeade5c2fe21f102403a29c02a69cd743c2fae924e7f1d15
[root@bigdatafat030161 chatbotapi-master-f94211c0795c6828e06a3e7fbb751fa624b89633]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
122af44829cd chatbot "/var/simple/entry..." 5 seconds ago Up 3 seconds 0.0.0.0:8001->8000/tcp chatbotapi4
73e61ad876e3 harbor.ppdaicorp.com/library/chatbotapi:v2 "/var/simple/entry..." 35 minutes ago Up 35 minutes 0.0.0.0:1025->8000/tcp chatbotapi3
a341f06d6d42 harbor.ppdaicorp.com/library/chatbotapi:v2 "/var/simple/entry..." 36 minutes ago Up 36 minutes 0.0.0.0:9000->8000/tcp chatbotapi2
132743c12d5d harbor.ppdaicorp.com/library/chatbotapi:v2 "/var/simple/entry..." 2 days ago Up 2 days 0.0.0.0:8000->8000/tcp chatbotapi
六、Dockerfile、Docker镜像和Docker容器的关系
Dockerfile 是软件的原材料,Docker 镜像是软件的交付品,而 Docker 容器则可以认为是软件的运行态。从应用软件的角度来看,Dockerfile、Docker 镜像与 Docker 容器分别代表软件的三个不同阶段,Dockerfile 面向开发,Docker 镜像成为交付标准,Docker 容器则涉及部署与运维,三者缺一不可,合力充当 Docker 体系的基石。
简单来讲,Dockerfile构建出Docker镜像,通过Docker镜像运行Docker容器。
我们假设这个容器的镜像通过以下Dockerfile构建而得:
FROM ubuntu:14.04
ADD run.sh /
VOLUME /data
CMD ["./run.sh"]
6.1 Dockerfile与Docker镜像
FROM ubuntu:14.04:设置基础镜像,此时会使用基础镜像 ubuntu:14.04 的所有镜像层,为简单起见,图中将其作为一个整体展示。
ADD run.sh /:将 Dockerfile 所在目录的文件 run.sh 加至镜像的根目录,此时新一层的镜像只有一项内容,即根目录下的 run.sh。
VOLUME /data:设定镜像的 VOLUME,此 VOLUME 在容器内部的路径为 /data。需要注意的是,此时并未在新一层的镜像中添加任何文件,即构建出的磁层镜像中文件为空,但更新了镜像的 json 文件,以便通过此镜像启动容器时获取这方面的信息。
CMD ["./run.sh"]:设置镜像的默认执行入口,此命令同样不会在新建镜像中添加任何文件,仅仅在上一层镜像 json 文件的基础上更新新建镜像的 json 文件。
因此,通过以上分析,以上的Dockerfile可以构建出一个新的镜像,包含4个镜像层,每一条命令会和一个镜像层对应,镜像之间会存在父子关系
6.2 Docker镜像与Docker容器的关系
Docker镜像是Docker容器运行的基础,没有Docker镜像,就不可能有Docker容器
可以理解的是:Docker镜像毕竟是镜像,属于静态的内容;而Docker容器就不一样了,容器属于动态的内容。动态的内容,大家很容易联想到进程,内存,CPU等之类的东西。的确,Docker容器作为动态的内容,都会包含这些。
为了便于理解,大家可以把Docker容器,理解为一个或多个运行进程,而这些运行进程将占有相应的内存,相应的CPU计算资源,相应的虚拟网络设备以及相应的文件系统资源。而Docker容器所占用的文件系统资源,则通过Docker镜像的镜像层文件来提供。
那么作为静态的镜像,如何才有能力转化为一个动态的Docker容器呢?此时,我们可以想象:第一,转化的依据是什么;第二,由谁来执行这个转化操作。
其实,转化的依据是每个镜像的json文件,Docker可以通过解析Docker镜像的json的文件,获知应该在这个镜像之上运行什么样的进程,应该为进程配置怎么样的环境变量,此时也就实现了静态向动态的转变。
谁来执行这个转化工作?答案是Docker守护进程。也许大家早就理解这样一句 话:Docker容器实质上就是一个或者多个进程,而容器的父进程就是Docker守护进程。这样的,转化工作的执行就不难理解了:Docker守护进程 手握Docker镜像的json文件,为容器配置相应的环境,并真正运行Docker镜像所指定的进程,完成Docker容器的真正创建。
Docker容器运行起来之后,Docker镜像json文件就失去作用了。此时Docker镜像的绝大部分作用就是:为Docker容器提供一个文件系统的视角,供容器内部的进程访问文件资源。
七、安装docker
7.1、准备工作
7.1.1 系统要求
Docker 支持 64 位版本 CentOS 7/8,并且要求内核版本不低于 3.10。 CentOS 7 满足最低内核的要求,但由于内核版本比较低,部分功能(如 overlay2 存储层驱动)无法使用,并且部分功能可能不太稳定。
7.1.2 卸载旧版本
旧版本的 Docker 称为 docker 或者 docker-engine,使用以下命令卸载旧版本:
yum remove docker
docker-client
docker-client-latest
docker-common
docker-latest
docker-latest-logrotate
docker-logrotate
docker-selinux
docker-engine-selinux
docker-engine
7.2 使用yum安装
yum install docker
service docker start
docker ps
service stop docker
systemctl restart docker
docker version
查看是否安装成功
[root@bigdatafat030178 ~]# docker run --rm hello-world
Unable to find image 'hello-world:latest' locally
Trying to pull repository docker.io/library/hello-world ...
latest: Pulling from docker.io/library/hello-world
2db29710123e: Pull complete
Digest: sha256:97a379f4f88575512824f3b352bc03cd75e239179eea0fecc38e597b2209f49a
Status: Downloaded newer image for docker.io/hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
服务器之间移动文件
scp -r -p 23245 dingshuai@10.114.26.81:/etc/ppd /etc/ppd