1.docker介绍
1.1什么是docker
Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源。
Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上。
1.2.docker底层原理介绍
Namespaces
命名空间(namespaces)是 Linux 为我们提供的用于分离进程树、网络接口、挂载点以及进程间通信等资源的方法。在日常使用 Linux 或者 macOS 时,我们并没有运行多个完全分离的服务器的需要,但是如果我们在服务器上启动了多个服务,这些服务其实会相互影响的,每一个服务都能看到其他服务的进程,也可以访问宿主机器上的任意文件,这是很多时候我们都不愿意看到的,我们更希望运行在同一台机器上的不同服务能做到完全隔离,就像运行在多台不同的机器上一样。
进程
进程是 Linux 以及现在操作系统中非常重要的概念,它表示一个正在执行的程序,也是在现代分时系统中的一个任务单元。在每一个 *nix 的操作系统上,我们都能够通过 ps 命令打印出当前操作系统中正在执行的进程,比如
网络
如果 Docker 的容器通过 Linux 的命名空间完成了与宿主机进程的网络隔离,但是却有没有办法通过宿主机的网络与整个互联网相连,就会产生很多限制,所以 Docker 虽然可以通过命名空间创建一个隔离的网络环境,但是 Docker 中的服务仍然需要与外界相连才能发挥作用。
每一个使用 docker run 启动的容器其实都具有单独的网络命名空间,Docker 为我们提供了四种不同的网络模式,Host、Container、None 和 Bridge 模式。
挂载点
虽然我们已经通过 Linux 的命名空间解决了进程和网络隔离的问题,在 Docker 进程中我们已经没有办法访问宿主机器上的其他进程并且限制了网络的访问,但是 Docker 容器中的进程仍然能够访问或者修改宿主机器上的其他目录,这是我们不希望看到的。
在新的进程中创建隔离的挂载点命名空间需要在 clone 函数中传入 CLONE_NEWNS,这样子进程就能得到父进程挂载点的拷贝,如果不传入这个参数子进程对文件系统的读写都会同步回父进程以及整个主机的文件系统。
1.3.Docker VS VM
Docker与虚拟机(虚拟机)的区别可以看:
左图是虚拟机的工作原理图,对资源进行抽象,着重体现在硬件层面的虚拟化上,这种方式增加了两场调用链,对性能的损耗比较大,而且还会占用大量的内存资源
有图是Docker的工作原理图,属于OS级别的虚拟化,kernel通过创建多个镜像来隔离不同的app进程,由于kernel是是共享,而且本身linux image也不大,性能损耗几乎可以不计,而且内存占用也不大,大大节约了设备成本。
Docker架构总览
最核心的是 Docker Daemon我们称之为Docker守护进程,也就是Server端,Server端可以部署在远程,也可以部署在本地,因为Server端与客户端(Docker Client)是通过Rest API进行通信。
docker CLI 实现容器和镜像的管理,为用户提供统一的操作界面,这个 客户端提供一个只读的镜像,然后通过镜像可以创建一个或者多个容器(container),这些容器可以只是一个RFS(Root File System),也可以是一个包含了用户应用的RFS。容器在docker Client中只是一个进程,两个进程是互不可见的。
用户不能与server直接交互,但可以通过与容器这个桥梁来交互,由于是操作系统级别的虚拟技术,中间的损耗几乎可以不计
1.4.Image & Container
在docker中,我们重点关注的就是镜像和容器了。因为在实际应用中,我们封装好镜像,然后通过镜像来创建容器,在容器运行我们的应用就好了。而server端掌控网络和磁盘,我们不用去关心,启动docker sever 和 docker client都是一条命令的事情。后面会详细讲docker的启动过程。
Image: 一个只读的镜像模板。可以自己创建一个镜像也可以从网站上下载镜像供自己使用。镜像包含了一个RFS.一个镜像可以创建很多容器。
Container:由docker client通过镜像创建的实例,用户在容器中运行应用,一旦创建后就可以看做是一个简单的RFS,每个应用运行在隔离的容器中,享用独自的权限,用户,网络。确保安全与互相干扰
两者在创建后,都是一堆layer的统一视角,唯一的却别是镜像最上面那一层是只读的,不可以修改,但是容器最上面一层是rw的,提供给用户操作
repository:仓库,这个东西没有单独介绍不是因为它不重要,而是因为之前做个比较多的Android源码编译,所以这里就没有仔细往下看,大概就是一个镜像库,最大的是docker hub,类似于google 的aosp,当然也可以本地搭,比如mig事业群就有自己的repo。
1.5.Docentos安装dokcer
# 安装依赖包
sudo yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
# 配置docker仓库源
sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
# 安装 docker
sudo yum install docker-ce docker-ce-cli containerd.io
# 启动
docker sudo systemctl start docker
1.6.Docker常用命令
获取镜像
从仓库获取所需要的镜像。
使用示例:
sudo docker pull tomcat:8.5
8.5: Pulling from library/tomcat
741437d97401: Pull complete
34d8874714d7: Pull complete
0a108aa26679: Pull complete
eea0f08c7492: Pull complete
ca74b3d90c15: Pull complete
f11a643c4a85: Pull complete
05eafed73b65: Pull complete
f24105f282aa: Pull complete
e27e73cbbd3f: Pull complete
801f808615c2: Pull complete
294f3735a5f6: Pull complete
Digest: sha256:2af4741120ac4b2e1993412e34b73565d1b859d8a44b1b5f0e1963d97cc921a1
Status: Downloaded newer image for tomcat:8.5
实际上相当于 docker pull registry.hub.docker.com/tomcat:8.5
命令,即从注册服务器 registry.hub.docker.com 中的 tomcat仓库来下载标记为 8.5 版本的镜像。
查看镜像列表
sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat 8.5 168588387c68 2 weeks ago 463MB
hello-world latest fce289e99eb9 8 weeks ago 1.84kB
利用 Dockerfile 来创建镜像
docker build
首先需要创建一个 Dockerfile
Dockerfile 中每一条指令都创建镜像的一层,例如:
FROM tomcat:8.5
MAINTAINER test <[email protected]>
# move all configuration files into container
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo 'Asia/Shanghai' >/etc/timezone
EXPOSE 8080
CMD ["catalina.sh", "run"]
Dockerfile 基本的语法是
- 使用#来注释
- FROM 指令告诉 Docker 使用哪个镜像作为基础
- 接着是维护者的信息
- RUN开头的指令会在创建中运行,比如设置时区
更详细的语法说明请参考 Dockerfile
编写完成 Dockerfile 后可以使用 docker build 来生成镜像。
sudo docker build -t yininfo/tomcat:8.5 .
Sending build context to Docker daemon 8.192kB
Step 1/6 : FROM tomcat:8.5
---> 168588387c68
Step 2/6 : MAINTAINER test <[email protected]>
---> Running in 3c123152dbb6
Removing intermediate container 3c123152dbb6
---> 1a4b1faa7d12
Step 3/6 : RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
---> Running in c47fd4b7e2d5
Removing intermediate container c47fd4b7e2d5
---> 54740c484571
Step 4/6 : RUN echo 'Asia/Shanghai' >/etc/timezone
---> Running in c14929176831
Removing intermediate container c14929176831
---> 106387d57685
Step 5/6 : EXPOSE 8080
---> Running in 10b1ff94dd17
Removing intermediate container 10b1ff94dd17
---> 02ca9a046384
Step 6/6 : CMD ["catalina.sh", "run"]
---> Running in 6fce494276e5
Removing intermediate container 6fce494276e5
---> 788874a002c0
Successfully built 788874a002c0
Successfully tagged yininfo/tomcat:8.5
其中 -t 标记来添加 tag,指定新的镜像的用户信息。 “.” 是 Dockerfile 所在的路径(当前目录),
也可以替换为一个具体的 Dockerfile 的路径。注意一个镜像不能超过 127 层。
用docker images 查看镜像列表
sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
yininfo/tomcat 8.5 788874a002c0 33 seconds ago 463MB
tomcat 8.5 168588387c68 2 weeks ago 463MB
hello-world latest fce289e99eb9 8 weeks ago 1.84kB
上传镜像
docker push
用户可以通过 docker push 命令,把自己创建的镜像上传到仓库中来共享。例如,用户在 Docker Hub 上完成注册后,可以推送自己的镜像到仓库中。
运行实例:
$ docker push yininfo/tomcat:8.5
创建容器
docker create <image-id>
docker create 命令为指定的镜像(image)添加了一个可读写层,构成了一个新的容器。注意,这个容器并没有运行。
docker create 命令提供了许多参数选项可以指定名字,硬件资源,网络配置等等。
运行示例:
创建一个centos的容器,可以使用仓库+标签的名字确定image,也可以使用image-id指定image。返回容器id
#查看本地images列表
docker images
#用仓库+标签
sudo docker create -it --name tomcat-8080 -p 8080:8080 yininfo/tomcat:8.5
6a006f9837f32c459d7b6945f367a7ab3896d6e238dadb4d9a0878a7a5d1b957
#可以使用 docker ps查看一件存在的容器列表,不加参数默认只显示当前运行的容器
$ docker ps -a
可以使用 -v 参数将本地目录挂载到容器中。
$ docker create -it --name tomcat-8080 -v /src/webapp:/opt/webapp yininfo/tomcat:8.5
这个功能在进行测试的时候十分方便,比如用户可以放置一些程序到本地目录中,来查看容器是否正常工作。本地目录的路径必须是绝对路径,如果目录不存在 Docker 会自动为你创建它。
启动容器
docker start <container-id>
Docker start命令为容器文件系统创建了一个进程隔离空间。注意,每一个容器只能够有一个进程隔离空间。
运行实例:
#通过名字启动
sudo docker start -i tomcat-8080
#通过容器ID启动
sudo docker start -i 6a006f9837f3
进入容器
docker exec <container-id>
在当前容器中执行新命令,如果增加 -it参数运行bash 就和登录到容器效果一样的。
sudo docker exec -it tomcat-8080 /bin/bash
停止容器
docker stop <container-id>
删除容器
docker rm <container-id>
运行容器
docker run <image-id>
docker run就是docker create和docker start两个命令的组合,支持参数也是一致的,如果指定容器
名字是,容器已经存在会报错,可以增加 --rm 参数实现容器退出时自动删除。
运行示例:
docker create -it --rm --name tomcat-8080 yininfo/tomcat:8.5
查看容器列表
docker ps
docker ps 命令会列出所有运行中的容器。这隐藏了非运行态容器的存在,如果想要找出这些容器,增加 -a 参数。
删除镜像
docker rmi <image-id>
删除构成镜像的一个只读层。你只能够使用docker rmi来移除最顶层(top level layer)
(也可以说是镜像),你也可以使用-f参数来强制删除中间的只读层。
commit容器
docker commit <container-id>
将容器的可读写层转换为一个只读层,这样就把一个容器转换成了不可变的镜像。
镜像保存
docker save <image-id>
创建一个镜像的压缩文件,这个文件能够在另外一个主机的Docker上使用。和export命令不同,这个命令
为每一个层都保存了它们的元数据。这个命令只能对镜像生效。
使用示例:
#保存centos镜像到centos_images.tar 文件
docker save -o yinfino-tomcat-8.5.tar yininfo/tomcat:8.5
容器导出
docker export <container-id>
创建一个tar文件,并且移除了元数据和不必要的层,将多个层整合成了一个层,只保存了当前统一视角看到
的内容。expoxt后的容器再import到Docker中,只有一个容器当前状态的镜像;而save后的镜像则不同,
它能够看到这个镜像的历史镜像。
inspect
docker inspect <container-id> or <image-id>
docker inspect命令会提取出容器或者镜像最顶层的元数据