1.什么是docker
要想使用linux容器,至少要在linux内核支持两种技术:namespace
和cgourps
我们可以在用户空间组织一些工具,利用内核提供的这些技术从而实现容器运行的目的
docker在容器运行、使用简化的道路上更近一步,使用镜像及分层构建的镜像的方式,使得容器技术的使用进一步被简化
因此,docker就是linux容器技术的一种实现形式,一种前端工具
2.docker相关机构及标准
后来,又出现了OCI
以及OCF
:
- OCI(Open Container Initiative)
- 由Linux基金会主导于2015年6月创立
- 旨在围绕
容器格式
和运行时
指定一个开放的工业化标准
- OCF(Open Container Format)
- runC是此种格式的主要实现形式之一
3.docker架构
3.1 组成部分
- 主要有三部分组成:
- client端/docker client
- server端/docker host/docker daemon(因此docker是c/s架构的应用程序)
- Containers/容器
- Images/镜像
- docker Registries(镜像仓库)(docker hub是其中最出名的一个)
无论是client端还是server端,都是由docker一个程序提供;该程序有很多子程序,其中有个子程序有一个子命令daemon
,即运行为守护进程;
因此若运行docker deamon
,意味着该主机成为一个守护进程服务器;它可以监听在某个作为的套接字之上,为了安全起见,仅提供本机的socket文件(unix socket文件)
unix本地套接字:通常套网络套接字socket API是通过IP+Port的方式实现多台主机通信的,当单台主机内进程间通信也可以通过127.0.0.1地址进行通信。而Unix本地套接字,其实就是一种专门用于本地(也就是单个主机上的)网络通信的一种方法
常见的docker镜像仓库:docker hub,阿里云仓库,
- 为什么叫docker registry 而不叫docker repository?
因为docker registry拥有两层功能:1.提供镜像存储的仓库 2.用户来获取竟像时的认证功能 3.提供了镜像文件的索引功能
在docker上,通常一个仓库/repo只放一个应用程序的镜像,但是该仓库里存放着该应用程序的不同版本的镜像(如一个nginx仓库存放多个版本nginx的镜像),因此提供了一个tag标签来标识不同版本的镜像文件(如,nginx:1.10),因此需要用仓库名+标签
来唯一标识一个镜像;而一个镜像可以有多个标签(如,一个stable标签会指向最新稳定版本,一旦最新稳定版本更新,该标签也会随之指向该版本的镜像)
因此在registry(如,docker hub)上会有很多的repo/仓库;一个repository是一个应用程序的集合,而registry则是repository的集合 - Repository和Registry区别
- Repository:
本身是一个仓库,这个仓库里面可以放具体的镜像,是指具体的某个镜像
的仓库,比如Tomcat下main有很多个版本的镜像,它们共同组成了Tomcat的Repository - Registry:
镜像的仓库,比如docker官方镜像仓库是Docker Hub,它是开源的,也可以私人部署一个,Registry上有很多Repository
,Redis、Tomcat、MySQL等等Repository组成了Registry - 如上图,docker的log,其中Repository就是一个一个的集装箱,而Registry则是鲸鱼
3.2 架构图
- 整体架构图
- 说明:
1. Docker Host与Registry之间默认是通过HTTPS协议通信的,也可以通过HTTP协议,前提是确认允许忽略安全问题
2. Docker Host中,可以直接通过socket/套接字进行监听的(通常是监听在Unix本地套接字上)
3. Client与Dcoker Host之间,由于Dcoker Host仅监听本地套接字文件,因此默认配置下,仅允许客户端在本地,也就是Docker daemon只能响应来自本地的Host的客户端请求
4.docker资源/对象
- images(只读/read-only,除非要重构镜像)
- containers
- networks
- volumes
- plugins
- others
说明1:
所有的资源对象都是可以单独地进行增删改查的
说明2:
镜像,是静态的,它不会运行
容器,是动态的,它有生命周期
容器和镜像的关系就类似进程和程序的关系;进程可以启动、终止,但是程序文件还在,同理,容器可以启动、终止,但是镜像文件还在
5.docker的安装与使用
5.1 依赖环境基础
- 64 bits CPU
- Linux Kernel 3.10+(Centos7.2的内核版本是3.10,也就是说尽量使用Centos7安装docker)
- lkLinux Kernel cgroups and namespace
5.2 安装docker的两种方式
- CentOS7默认
“Extras” repository ,该仓库中有docker,如下
https://mirrors.tuna.tsinghua.edu.cn/centos/7/extras/x86_64/Packages/
通常不用Centos自带的docker
- 单独/第三方的仓库下载docker
如,以清华镜像站为例,
https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/docker-ce.repo
将该repo文件下载到/etc/yum.repos.d/下
[root@vincent yum.repos.d]# wget https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/docker-ce.repo
更改该repo文件中默认的baseurl的地址,如在清华镜像站中docker-ce里centos7 x86_64的具体url为
https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/7/x86_64/stable/Packages/
用https://mirrors.tuna.tsinghua.edu.cn/docker-ce/
替换原repo文件中basurl的前缀部分https://download.docker.com/
vim中批量替换掉方法如下
:%s@https://download.docker.com/@https://mirrors.tuna.tsinghua.edu.cn/docker-ce/@
通过yum repolist
查看当前仓库信息,可以看到docker-ce已有程序包
通过yum install docker-ce
(1.使用默认的Extra则yum install docker;2.区分ce概念)
如上,安装完毕!
5.3 docker配置文件
- docker-ce的配置文件
/etc/docker/daemon.json
,初次安装默认该目录及文件不存在,如果需要启动前定义某些配置,需要手动创建该目录及配置文件(比如配置镜像加速器) - docker镜像加速
- doker.cn
- 阿里云加速器
- 中国科技大学加速器
比如,若使用docker.cn加速器,则需要在daemon.json中增加如下json格式的数组配置
{
"registry-mirrors":["https://registry.docker-cn.com"]
}
5.4 docker启用
[root@vincent docker]# systemctl start docker.service
[root@vincent docker]#
可以直接通过docker
命令来打印docker的说明信息来确定docker启动成功
5.5 docker常用命令
- 命令说明
老版本中,docker的命令是直接docker+command
的形式,比如docker create
代表新建容器,后来新版本中,docker将各个命令进行了分组管理,比如原来的docker create
分到了container
组中,新命令为docker container create
为了兼容,新版docker也是兼容老版本命令格式的,但是建议后续要用新的分组管理的命令形式 - 常见命令
docker --help # 展示docker命令帮助手册
docker <命令分组> --help # 展示docker某分组下的命令帮助手册
docker <命令组> <命令> --help # 具体命令的具体参数使用方法
命令(old) | 命令(new) | 说明 |
docker search | docker search | search the Docker Hub for images |
docker pull | docker image pull | pull an image |
docker images | dockre image ls | list images |
docker create | docker container create | create a new container |
docker start | docker container start | start one ore more containers |
docker run | docker container run | run a command in a new container |
docker attach | docker container attach | attach to a running container |
docker ps | docker container ls | list containers |
docker logs | docker container logs | fetch the logs of a container |
docker restart | docker container restart | restart a container |
docker stop | docker container stop | stop one or more running containers |
docker kill | docker container kill | kill one or more running containers |
docker rm | docker container rm | remove one or more containers |
docker version | - | show the version of docker client/server |
docker info | - | show the detailed information of docker |
5.6 docker镜像说明
我们通过docker search nginx
查看nginx的镜像,如下
- 顶级仓库
我们能看到标注出来的nginx
没有任何任何分隔符,直接就是应用程序名,叫做顶级仓库
,docker hub官方的仓库 - 用户/项目仓库
从名称上来看是存在分隔符的,由于docker hub是允许个人创建账号并上传自己制作的镜像,因此这种叫做用户仓库
或者项目仓库
- alpine版镜像说明
我们从hub.docker.com
中查看某些应用的镜像,会发现每个应用都有不同的tag,比如stable、lastest、alpine等,其中alpine是简洁版,专门构建小的镜像文件的微型发行版,能给程序运行提供基础环境,但体积非常小;但是缺少将来可能用到的调试工具(测试可使用,生产环境不建议) - 私有仓库
自己用服务器做一个registry,可以存放常用镜像和自己制作的镜像,规避了由于网络导致的上传下载的问题
5.7 拉取镜像
- 拉取镜像文件
docker pull <registry>[:<port>]/[<namespace>/]<name>:<tag>
[root@vincent ~]# docker image pull nginx:1.14-alpine
1.14-alpine: Pulling from library/nginx
bdf0201b3a05: Pull complete
3d0a573c81ed: Pull complete
8129faeb2eb6: Pull complete
3dc99f571daf: Pull complete
Digest: sha256:485b610fefec7ff6c463ced9623314a04ed67e3945b9c08d7e53a47f6d108dc7
Status: Downloaded newer image for nginx:1.14-alpine
docker.io/library/nginx:1.14-alpine
You have mail in /var/spool/mail/root
[root@vincent ~]#
[root@vincent ~]# docker image pull busybox
Using default tag: latest
latest: Pulling from library/busybox
76df9210b28c: Pull complete
Digest: sha256:95cf004f559831017cdf4628aaf1bb30133677be8702a8c5f2994629f637a209
Status: Downloaded newer image for busybox:latest
docker.io/library/busybox:latest
[root@vincent ~]#
- 列出镜像文件相关信息
[root@vincent ~]# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
busybox latest 1c35c4412082 3 weeks ago 1.22MB
nginx 1.14-alpine 8a2fb25a19f5 14 months ago 16MB
[root@vincent ~]#
- 镜像文件字段介绍
- RePOSITORY:仓库名称
- TAG:镜像标签
- IMAGE ID:镜像唯一标识ID
- GREATED:镜像创建时间
- SIZE:镜像文件大小
6.容器的相关操作
一般新建并运行一个容器,可以用docker container run
或 docker container create
+docker container start
- docker container run 常见参数说明
语法格式:
docker container run [OPTIONS] IMAGE [COMMAND] [ARG...]
参数 | 说明1 | 说明2 |
- t | Allocate a pseudo-TTY | 运行为交互式接口 |
- i | Keep STDIN open even if not attached | 交互式访问 |
– name str | Assign a name to the container | 给容器命名 |
– network str | Connect a container to a network | 指定容器网络,有默认网络 |
– rm | Automatically remove the container when it exits | 容器停止后,自动删除 |
- d | Run container in background and print container ID | 容器启动后直接运行在后台 |
- exec | Run a command in a running container | 跨越容器边界,在运行的容器中执行命令 |
- docker网络
关于容器的网络,,可以通过docker network ls
看下当前有多少网络,默认是bridge网络,默认是172.17.
网段,且是nat桥
/地址转换桥
[root@vincent ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
78a835505101 bridge bridge local
38517f976413 host host local
09a904f816d0 none null local
[root@vincent ~]#
docker启用之后就会默认有一个docker0
的网络,默认地址是172.17.
段
[root@vincent ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether fa:16:3e:6e:05:b6 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.16/24 brd 10.0.0.255 scope global eth0
valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:37:52:3a:46 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
[root@vincent ~]#
6.1 以busybox为例操作容器
- 以busybox镜像启动容器
用busybox:latest
镜像,以交互式、带终端的方式创建并启动一个名为b1
的容器
[root@vincent ~]# docker container run --name b1 -it busybox:latest
[root@vincent ~]# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
busybox latest 1c35c4412082 3 weeks ago 1.22MB
nginx 1.14-alpine 8a2fb25a19f5 14 months ago 16MB
[root@vincent ~]#
[root@vincent ~]# docker container run --name b1 -it busybox:latest
/ #
/ #
用docker container ps
查看当前容器
说明:
run命令后面跟的镜像名由REPOSITORY
+TAG
组成;若该镜像文件在本地不存在,则会默认到网上的registory去拉取
ps命令默认仅显示运行中的容器,如果容器存在但是处于未运行/停止状态则同样不会打印出来
- 测试httpd服务
新建一个测试用的index.html文件,并写入测试的文字,然后启动httpd并服务指向该文件
/ # mkdir /home/html
/ # vi /home/html/index.html
/ # httpd -f -h /home/html/
index.html文件内容:this is a httpd by busybox in docker container test
通过docker inspect b1
命令httpd服务的ip地址
"IPAddress": "172.17.0.2"
在全局环境中,通过curl命令测试httpd服务
[root@vincent /]# curl 172.17.0.2
this is a httpd by busybox in docker container test
[root@vincent /]#
- 停止b1容器
docker container stop [OPTIONS] CONTAINER [CONTAINER...]
- -t, --time int:Seconds to wait for stop before killing it (default 10)/不加则默认10s停止
[root@vincent /]# docker container stop b1
b1
[root@vincent /]#
由于busybox是一个shell进程,因此直接通过exit退出后,容器也会自动停止
/ # exit
[root@vincent ~]#
用docker container ps
查看当前容器
用docker container ps -a
查看当前容器
- 启动b1容器
docker container start [OPTIONS] CONTAINER [CONTAINER...]
- -a, --attach:Attach STDOUT/STDERR and forward signals/连接容器并打印输出或错误
- -i, --interactive:Attach container’s STDIN/启动容器并进入交互模式
[root@vincent ~]# docker container start -i -a b1
/ #
说明:
若要启动的容器并非shell,而是一个nginx守护进程,不用加-ai
直接启动即可
- 删除b1容器
删除容器,要先保证容器处于停止状态
docker container rm [OPTIONS] CONTAINER [CONTAINER...]
[root@vincent /]# docker container rm b1
b1
[root@vincent /]#
用docker container ps -a
查看当前容器
6.2 以nginx为例操作容器
- 以nginx镜像启动容器
因为nginx不需要交互式,因此直接后台运行该容器即可
[root@vincent ~]# docker container run --name web1 -d nginx:1.14-alpine
8832469ea98425d6367f41f239c7ca53df1d868adb0acf722eef6f2bf819d68d
[root@vincent ~]#
用docker container ps
查看当前容器
说明:
nginx -g 'daemon of...'
指定该程序不要运行在后台
。对于docker容器来说,一个容器仅能运行一个程序,如果该程序还去后台运行,则容器会认为自身内部没有程序在运行,那么容器就会自动结束
因此,要注意,容器里的程序不能跑在后台,程序本身就是这个容器的骨架
- 测试nginx服务是否启动
通过docker inspect b1
命令httpd服务的ip地址
"IPAddress": "172.17.0.2"
在全局环境中,通过curl命令测试nginx服务
[root@vincent ~]# curl 172.17.0.2
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@vincent ~]#
- exec命令绕过容器边界
docker container exec [OPTIONS] CONTAINER COMMAND [ARG...]
- -i, --interactive:Keep STDIN open even if not attached
- -t, --tty:Allocate a pseudo-TTY
[root@vincent ~]# docker container exec -it web1 /bin/sh
/ # ps
PID USER TIME COMMAND
1 root 0:00 nginx: master process nginx -g daemon off;
6 nginx 0:00 nginx: worker process
12 root 0:00 /bin/sh
17 root 0:00 ps
/ #
/ # netstat -tnl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
/ #
- 查看docker容器中进程的日志
docker容器的日志默认打到工作台,而不是存到日志,可以直接通过命令查看
[root@vincent ~]# docker container logs web1
172.17.0.1 - - [27/Jun/2020:05:42:52 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
[root@vincent ~]#
6.3 以redis为例(本地无镜像)操作容器
- 创建并启动容器
本地并没有redis:4-alpine
镜像文件,因此默认会去网上下载
[root@vincent ~]# docker run --name kvstor1 -d redis:4-alpine
Unable to find image 'redis:4-alpine' locally
4-alpine: Pulling from library/redis
cbdbe7a5bc2a: Pull complete
dc0373118a0d: Pull complete
cfd369fe6256: Pull complete
152ffd6a3b24: Pull complete
7c01860f13a3: Pull complete
aa6ecacd3bee: Pull complete
Digest: sha256:aaf7c123077a5e45ab2328b5ef7e201b5720616efac498d55e65a7afbb96ae20
Status: Downloaded newer image for redis:4-alpine
67c805d9bef3a0ea16033a71acb7a048dd6789409838b029d3e49de674596471
[root@vincent ~]#
用docker container ps
查看当前容器
- exec命令绕过容器边界
[root@vincent ~]# docker container exec -it kvstor1 /bin/sh
/data # ps
PID USER TIME COMMAND
1 redis 0:00 redis-server
12 root 0:00 /bin/sh
19 root 0:00 ps
/data # netstat -tnl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN
tcp 0 0 :::6379 :::* LISTEN
/data # redis-cli -p 6379
127.0.0.1:6379>
127.0.0.1:6379> KEYS *
(empty list or set)
127.0.0.1:6379> exit
/data #
/data # exit
[root@vincent ~]#
7.容器状态转换图