docker容器技术基础入门(一)
目录
一、前言:
二、docker architecture---docker的架构图
关于仓库的解释:
三、配置阿里云docker镜像加速
四、安装及使用docker
4.1、依赖及基础环境:
4.2、centos 7安装方式
1、extras repository;
2、docker-ce的配置文件;需要手动创建
4.3 docker的使用及命令细节剖析
4.3.1 docker如何启动及查看信息
启动docker服务:
查看docker信息:
查看docker更详细的信息:
4.3.2docker内部常用操作:
根据我们的关键词nginx搜索镜像
下载镜像到本地
列出本地所有可用镜像
删除一个镜像:
创建docker容器(注意并不会启动容器):
启动docker容器:
停止正在运行的docker容器:
强行停止正在运行的docker容器:
创建docker容器并直接启动该容器:
删除docker容器:
暂停docker容器:
取消暂停docker容器:
哪些容器更耗资源:(可以根据资源消耗比例进行排序)
显示docker容器:不显示处于停止状态的容器的
列出所有dicker容器:不显示处于停止状态的容器的
busybox例子:
下面我们在举一个nginx的例子:
举一个redis的例子:
在运行的容器中执行命令
五、描述了docker的容器的状态转换和相关各种常用命令的图解:
在上一篇文章我们介绍了docker容器技术,LXC他们之间的关系及由来。
那我们知道要想使用linux容器,至少在linux内核级中要支持两种技术:1.namespaces(我们称为名称空间)2.Cgroups(control groups)。
接着我们可以借助于在用户空间组织一些工具,利用内核级所提供的这些技术,从而实现容器运行之目的,而后docker在容器运行使用简化的道路上又进一步,他们提供了镜像,而且是分层构建的镜像的方式,使得容器技术的使用更加被简化。
后来呢,在docker主导下,又有了OCI(Open Container Initiative,由Linux基金会主导于2015年6月创立。旨在围绕容器格式和运行时指定一个开放的工业标准,由两部分组成1. the Runtime Specification:运行时标准 2.the image Specification:镜像格式标准),runC(OCF:Open Container Format叫开放的容器格式。而runC是OCF的重要实现之一)容器引擎,这样的格式或者说是标准。而runC就是docker新版本中使用的容器引擎。
而docker专门提供了一个容纳容器镜像的站点我们成为dockerhub(地址为hub.docker.com),在这个网站中可以找到大多数的容器镜像。
docker由这么几部分组成:Client端,server端(我们称为DOCKER_HOST)和registries(默认的位置为docker Hub)
所以我们可以认为docker是C/S架构的应用程序,事实上无论是C端还是S端,都由docker一个程序提供,这个程序有很多子程序,其中有一个子程序或者叫子命令叫daemon,他就表示运行为守护进程。所以当我们运行docker daemon就把这台主机变成守护进程服务器,他可以监听在我们的套接字之上。这种套接字为了安全起见,他默认只提供本机的unix socket文件的套接字。
docker_host是真正运行容器的主机,其特征为 有Containers(容器)和Images(镜像)两部分。他们两个是docker主机上非常重要的组成部分。
镜像来自于Registry(注册表,但是此处我们可以称为叫docker的镜像仓库,默认就是Docker Hub),docker在创建容器时,Docker会先检查本地是否有镜像,默认镜像是本地没有的,如果没有会到docker hub上去下载指定的镜像到本地(因为镜像是分层构建的),并且下载下来的镜像在容器使用结束后不会删除,镜像是可以共享的,尤其是基础镜像是可以共享给多个上述镜像使用的,镜像是不可修改的是只读的,只能重构。
所以启动容器的时候就是基于镜像启动,在镜像的基础之上为一个容器创建一个专用的可写仓,从而来启动一个容器。所以镜像也需要在docker主机的本地存储。
那么到底我们会在这个主机上运行那些容器事先无法评估。因此就有Registry专门的仓库来放镜像,注意docker Hub上所放的镜像估计有几十万个之多。所以不可能把没有镜像都放在本地。因此这也就是为什么放在公共存储位置,你用到那个就下载那个的原因。但是我们只要是用,就必须先把镜像加载到本地。这里加载所用到的协议是http或https。默认必须使用https,因为安全。同样的Client和docker_host之间也使用这两个协议,因为docker的api也是一个标准的restful风格的api,当然这里我们基于本地的socket文件通信没必要考虑那么复杂,但是我们也要知道他的应用层协议也是http的就可以了。
所以我们要使用docker就需要把docker的应用程序包下载下来安装即可。但是docker的运行过程当中,尤其是创建容器的时可能有一点慢,原因在于是第一次要去下载镜像。这个下载镜像的速度取决于你的互联网连接速度。更何况docker的服务器还在国外。所以为了实现加速访问,docker在国内做了一个docker镜像服务器,成为docker CN,但是他的镜像加速效果不太好。当然我们也可以使用阿里云所提供的加速。中国科技大学也有docker的镜像。不过dockerCN的加速是公开的任何人都可以直接使用。而使用阿里云的docker加速需要每一个人自己的私有账号
关于仓库的解释:
docker的镜像是分层构建的。
Docker Registry拥有两个功能,
第一:提供镜像存储的仓库。
第二:提供用户来获取镜像时的认证等功能同时还提供了当前服务器上所有可用镜像的搜索索引。
在一个Docker Registry上仓库会有很多,一个docker镜像仓库 有仓库的名称,一个仓库叫做一个repository(简称repo),而一个仓库通常只用来放一个应用程序的镜像。假如我们的nginx做了一个镜像,对于nginx来讲有自己的应用版本(例如nginx1.0和niginx1.2)所以镜像也会有应用到不同应用程序上的版本镜像,所以为了能够使得镜像和应用程序版本之间有意义上的关联关系:那么在docker上通常一个仓库只放一个应用程序的镜像,仓库名就是应用程序名nginx,里面放很多niginx的版本,为了标记每一个镜像,通常给每一个镜像额外添加一个组件叫标签tag,来标识每一个镜像。那么我们就叫nginx1.10版本的镜像为 nginx:1.10 ,这个就是镜像名,那么用仓库名加标签 才能用来唯一标识一个镜像,所以这个nginx是仓库名不是镜像名,镜像名的唯一标识是 标签。如果有人访问的时候只给了仓库名没给标签,那么我们应该给他默认的。默认通常是最新的版本,一个镜像是可以有多个标签的,例如叫niginx:1.15同时我们也给他取一个镜像名叫ngixn:latest就是最新版,随后等1.16出来以后,最新版就是不是1.15的引用了,我们要引用到1.16上,所以这个lastest会经常改的,通常指向这个仓库的最新版本,但是也有可能指向的是这个仓库的最新的稳定版本。在nginx的次版本号为奇数是开发版,因此我们要使用最新的稳定版通常应该是1.14的。所以其标记应该为nginx:1.14和nginx:stable,而稳定版通常指向最新的稳定版。就类似于这种格式。所以在docker Hub上仓库就有非常多了。同时在Hub里面我们还有基础层的系统,比如就是一个独立的操作系统。Centos里面的bashshell。
镜像:静态的
容器:动态的,有生命周期
注意任何一个restful风格的资源对象是支持增删改查的操作。因为镜像和容器都支持增删改查。
networks:网络,也是一个独立的对象,单独执行增删改查操作。
volumes:存储卷,卷就是为了能够给容器提供持久存储的存储空间。通常在外部的网络存储设备之上。可以单独的增删改查
plugins:插件。增删改查
那么这些我们统统成为 对象
打开这个网站https://dev.aliyun.com/search.html
点我直达
本文介绍的是在centos7.4下安装docker,如您需要在windows下安装docker请点击下面的按钮,跳转到我的另一篇文章
点我去看windows安装及使用docker
1、64 bits CPU
2、Linux Kernel 3.10+
3、 Linux Kernel cgroups and namespaces
cd /etc/yum.repos.d/
wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum repolist
yum install docker-ce
默认centos7的yum仓库extras就有docker,版本比较老,下载新版本的docker的yum仓库
[root@MiWiFi-R3L-srv ~]# cd /etc/yum.repos.d/
[root@MiWiFi-R3L-srv yum.repos.d]# wget
[root@MiWiFi-R3L-srv yum.repos.d]# sed -i 's# docker-ce.repo
[root@MiWiFi-R3L-srv yum.repos.d]# yum update
[root@MiWiFi-R3L-srv yum.repos.d]# yum install docker-ce
[root@MiWiFi-R3L-srv yum.repos.d]# mkdir /etc/docker/
[root@MiWiFi-R3L-srv docker]# echo -e '{\n\t"registry-mirrors": ["https://registry.docker-cn.com"]\n}' >/etc/docker/daemon.json
[root@MiWiFi-R3L-srv docker]# systemctl start docker.service #启动docker
[root@MiWiFi-R3L-srv docker]# docker info
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 0
Server Version: 18.06.1-ce
Storage Driver: overlay2 # docker要实现分层构建,联合挂载。必须使用这种文件系统来支持。在centos7.4以前用的是device mapper,这种是lvm的实现,在docker上性能极差,还不稳定,已经废弃。
......
......
......
在能看到上面的一系列信息,说明docker已经安装成功并可以使用了
启动docker服务:
[root@node1 yum.repos.d]# systemctl start docker.service
查看docker信息:
[root@node1 yum.repos.d]# docker version
查看docker更详细的信息:
[root@node1 yum.repos.d]# docker info
关于上图参数的解释:
Containers:容器有多少个
Running:其中处于运行状态的多少个
Paused:其中处于暂停状态的多少个
Stopped:其中处于停止状态的多少个
Images:有多少个镜像
Server Version:服务器版本
Storage Driver:存储驱动后端,docker镜像是分层构建,联合挂载,这两个的要求必须使用特殊的文件系统或者叫存储格式(存储驱动)才能实现。AUFS和overlay2。centos7.4之前的版本有可能用的是Device mapper(就是LVM的实现,性能极差而且不稳定)。
Backing Filesystem:
Plugins:指的是插件有那几个
Volume:存储插件
Network:网络插件
Log:日志插件
Security Options:安全选项
Kernel Version:内核版本
如果你使用了方式2安装还能看到下图所示的信息:
注意上图的格式是最原始的格式,命令不带分组的格式。
根据我们的关键词nginx搜索镜像
[root@node1 yum.repos.d]# docker search nginx
下载镜像到本地
[root@node1 yum.repos.d]# docker pull xxx下载到本地,命令也可以用分组的方式 docker image pull xxx 是一样的效果
列出本地所有可用镜像
[root@node1 yum.repos.d]# docker images列出本地所有可用镜像,命令也可以用分组的方式 docker image ls 是一样的效果
如果为如下图所示:
PEPOSITORY:仓库名称
TAG:标签
IMAGE ID:镜像自己的唯一标识
CREATED:大概是什么时候创建的
SIZE:体积
还可以使用[root@node1 ~]# docker image ls --no-trunc来显示完整的信息
默认情况下只会显示前12位。
我们在显示镜像的时候也可以过滤:比如我们只显示某个镜像,只显示某个仓库的镜像
还可以使用docker image ls --format string 使用Go模板进行过滤
3、docker 仓库格式
[root@MiWiFi-R3L-srv docker]# docker search nginx
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
nginx Official build of Nginx. 10034 [OK]
jwilder/nginx-proxy Automated Nginx reverse proxy for docker con?? 1440 [OK]
richarvey/nginx-php-fpm Container running Nginx + PHP-FPM capable of?? 633 [OK]
jrcs/letsencrypt-nginx-proxy-companion LetsEncrypt container to use with nginx as p?? 428 [OK]
kong Open-source Microservice & API Management la?? 237 [OK]
webdevops/php-nginx Nginx with PHP-FPM 117 [OK]
kitematic/hello-world-nginx A light-weight nginx container that demonstr?? 112
zabbix/zabbix-web-nginx-mysql Zabbix frontend based on Nginx web-server wi?? 74 [OK]
bitnami/nginx Bitnami nginx Docker Image 58 [OK]
1and1internet/ubuntu-16-nginx-php-phpmyadmin-mysql-5 ubuntu-16-nginx-php-phpmyadmin-mysql-5 48 [OK]
linuxserver/nginx An Nginx container, brought to you by LinuxS?? 42
tobi312/rpi-nginx NGINX on Raspberry Pi / armhf 23 [OK]
blacklabelops/nginx Dockerized Nginx Reverse Proxy Server. 12 [OK]
wodby/drupal-nginx Nginx for Drupal container image 11 [OK]
centos/nginx-18-centos7 Platform for running nginx 1.8 or building n?? 8
webdevops/nginx Nginx container 8 [OK]
nginxdemos/hello NGINX webserver that serves a simple page co?? 8 [OK]
centos/nginx-112-centos7 Platform for running nginx 1.12 or building ?? 5
1science/nginx Nginx Docker images that include Consul Temp?? 4 [OK]
travix/nginx NGinx reverse proxy 2 [OK]
mailu/nginx Mailu nginx frontend 2 [OK]
pebbletech/nginx-proxy nginx-proxy sets up a container running ngin?? 2 [OK]
toccoag/openshift-nginx Nginx reverse proxy for Nice running on same?? 1 [OK]
ansibleplaybookbundle/nginx-apb An APB to deploy NGINX 0 [OK]
wodby/nginx Generic nginx 0 [OK]
上面列表中,没有/分隔开的仓库是顶级仓库,一般是docker hub官方的。带/分隔开的是个人用户创建的镜像
可以用下图所示的Tags来看每个版本的大小
alpine:是专门用来构建非常小的镜像文件的一个微型发行版。他能够给你的程序运行提供基础环境但体积非常小,但是可能会有一些问题,可能缺少我们将来调试的工具。所以相当不建议在生产环境中使用alpine版本。尽量自己做镜像,里面带调试工具的。然后上传到docker Hub上,但是镜像可能很大,我们上传和下载都很慢。所以我们可以建私有Registry
下面我们举个栗子:
下载镜像:
[root@node1 ~]# docker image pull nginx:1.14-alpine
查看镜像是否下载成功:
[root@node1 ~]# docker image ls
我们继续下载一个叫做busybox的镜像
[root@node1 ~]# docker pull busybox:latest
也可以不写latest,默认就是latest
删除一个镜像:
docker rmi xxx或者docker image rm xxx
创建docker容器(注意并不会启动容器):
可以使用docker container create或者docke create
启动docker容器:
docker container start xxx或者docker start xxx
停止正在运行的docker容器:
docker container stop xxx
强行停止正在运行的docker容器:
docker container kill xxx
创建docker容器并直接启动该容器:
docker container run xxx或者docker run xxx
参数详解见下文
删除docker容器:
docker container rm xxx或者docker rm xxx
暂停docker容器:
docker container pause xxx
取消暂停docker容器:
docker container umpause xxx
哪些容器更耗资源:(可以根据资源消耗比例进行排序)
docker container top
显示docker容器:不显示处于停止状态的容器的
docker container ls
如要要显示处于停止状态的容器:
docker container ls -a
列出所有dicker容器:不显示处于停止状态的容器的
docker ps
如要要显示处于停止状态的容器:
docker ps -a
CONTAINER ID:容器自有ID
IMAGE:基于哪个镜像启动的容器
COMMAND:在容器中运行了什么命令,当我们基于一个镜像启动容器的时候,每个镜像都有他自己定义默认要运行的程序,如果没指就运行自己默认的程序,但是我们也可以改,我就不运行这个镜像默认的程序,他里面还有别的程序。也可以的。
CREATED:容器在什么时候创建的
STATUS:当前处于什么状态
PORTS:监听了什么端口,其实不是监听,而是映射,后面具体再说
NAMES:容器的名字,名字是可以省略的,省略了就用ID表示
4、启动一个docker镜像
在使用run的时候,镜像是不可省略的。必须要指明run哪个镜像
docker run命令启动容器时会先在本地仓库查找镜像,如果没有在去docker hub仓库中下载镜像并启动
如果不指定这个镜像启动起来运行什么命令,他将运行镜像的默认命令,当然我们可以自己给他传递一个命令[COMMAND]并向命令传递参数[ARG...]
我们还可以在启动容器的时候加上选项[OPTIONS]
如果我们要运行一个交互式接口,像使用一个虚拟机一样来使用它,打开shell
-t:在新容器内指定一个伪终端或终端。没有终端是无法打开shell的
-i:允许你对容器内的标准输入 (STDIN) 进行交互。
所以我们要需要使用上述的 -t -i
一般来讲我们启动容器的时候要给他一个名字,因此还要使用 --name
如果有必要也可以在启动容器的时候给他加入一个网络 --network
如果不加network,那么将使用默认的叫bridge的网络
使用[root@node1 ~]# docker network ls能显示本地有多少个网络
有三个叫bridge,host,none。我们后面再详细讲
而bridge到哪里去,可以使用[root@node1 ~]# ifconfig命令查看
有本地桥叫docker0,docker启动之后会自动创建一个docker桥叫docker0,而且默认网段是172,17网段的。任何启动的容器都会自动拥有这个网络地址,而且这个桥是net桥,是地址转换桥,也就意味着可以通过地址转换转换成可以对外通讯的这个地址(上图是192.168.123.101)
如果容器一停,可以让他自动就删除:(注意有些选项是互斥的不能同时用)
还可以让容器启动 运行到后台
-d 表示脱离于当前终端的关系,否则他将一直占据了终端
下面我们将基于busybox启动一个很小很小的用户空间作为案例:(运行latest版本可以不写:laest)
[root@node1 ~]# docker run --name b1 -it busybox:latest
这个命令默认是运行一个shell接口的,如下图所示打开一个shell
ls /bin 可以看到这里面有很多的命令,他们都是busybox的命令
注意我们现在运行的是一个shell,你在里面可以运行很多shell的子命令
可以发现我们的sh的PID号为1,这就表示为init,是整个用户空间的总管进程,如果他宕了整个用户空间就宕了,用户空间宕了,相当于整个容器就要关闭了。
我们要运行其他进程,就相当于sh的子进程而已。比如像http就需要-h来告诉我们详细用法
下面是例子:
在里面写入Busybox httpd server.的内容
下面我们启动httpd
不加 -f 就是后台,加-f就是前台。-h指明家目录地址
回车,他默认监听了80端口。
这时候我们可以查看一下运行了哪些容器(参数说明在前面有介绍)
看不到PORTS是因为没有做端口映射,映射我们后面再解释
那么对于b1这个容器,他的地址是多少呢?我们使用命令[root@node1 ~]# docker inspect b1
可以看到地址是172.17.0.2
所以我们使用curl 172.17.0.2来访问
现在我们用的是特权用户空间跟刚才新创建的叫做b1的用户空间里面的容器进行交互的。相当于两个虚拟机之间的通信。
而后我们要退出,不要ctrl+c,因为在shell中exit表示退出,如果sh一终止,容器就终止了。
注意现在容器看不到了。ps是不显示已停止的容器的。所以我们需要使用命令如下,加上-a即可
那么对于停止状态的容器我们还可以启动起来,使用启动容器docker start xxx
-a:并附加到他的终端上(在新容器内指定一个伪终端或终端。没有终端是无法打开shell的)
-i:如果里面默认运行shell,你要进入交互式接口就需要使用-i
如果之间运行的不是shell,就是个守护进程那么不用加-ai 直接启动就行。
再使用下面命令查看又处于up状态
下面我们不让他运行了。
注意docker kill和docker stop的区别在于:就相当kill给他发了kill -9信号,stop给他发了kill -15信号这样。
系统会发送一个SIGTERM的信号给对应的程序。当程序接收到该signal后,将会发生以下的事情
- 程序立刻停止
- 当程序释放相应资源后再停止
- 程序可能仍然继续运行
大部分程序接收到SIGTERM信号后,会先释放自己的资源,然后在停止。但是也有程序可以在接受到信号量后,做一些其他的事情,并且这些事情是可以
配置的。如果程序正在等待IO,可能就不会立马做出相应。
也就是说,SIGTERM多半是会被阻塞的、忽略。
-9 的效果是立即杀死进程. 该信号不能被阻塞, 处理和忽略。
-15的效果是正常退出进程,退出前可以被阻塞或回调处理。并且它是Linux缺省的程序中断信号
所以正常情况下不要强制终止,可能会导致数据丢失的。这里我们为了测试
此时又处于停止状态了。处于停止状态是可以删除的
直接启动nginx
[root@node1 ~]# docker run --name web1 -d nginx:1.14-apline
因为nginx里面没有shell。我们不需要跟它进行交互,所以必要 -i 了,直接 -d 让他到后台去运行
COMMAND:表示不要跑在后台。一个容器就是为了运行一个程序,如果这个程序跑后台去运行,那么就没有任何程序了,它就认为这个程序终止了。那么容器就结束了。在容器中跑任何程序,包括服务程序,一定不能在容器中运行在后台的。只要运行在后台,一启动就终止。
PORTS:监听的是80端口
那么到底使用的是什么地址呢?同样的使用[root@node1 ~]# docker inspect b1
所以我们再次使用curl访问
如果要跑一个redis就使用下面的
那么我们想测试怎么办?这个镜像当中自带客户端,那么我们可以绕过容器的边界,登陆进去。
在运行的容器中执行命令
使用docker container exec xxxx 是在容器中执行另外一个命令,或者使用docker exec xxx
语法
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
OPTIONS说明:
-d :分离模式: 在后台运行
-i :即使没有附加也保持STDIN 打开
-t :分配一个伪终端
注意:要指明在哪个容器中,执行什么命令
注意要能交互,必须要给他附加终端并交互式登陆
[root@node1 ~]# docker exec -it kvstor1 /bin/sh
所以在一个容器中运行多个进程是可以的,但是我们通常是这样的目的才使用多进程,到里面去探测,探查他的运行情况是不是正常的。
这个命令是绕过容器去看容器是怎么运行时候用的。
使用netstat -tnl来看看有没有监听6379端口,还可以使用redis的客户端
如果我们想改配置文件直接vi就行,但是这样很麻烦,所以就带给我们一个难题,我们想配置容器就很麻烦了。
现在我们想我们的nginx的日志放在哪里呢?是在var/log下面么?但是我们现在整个容器只是为了运行这一个进程,我们还有必要非得把它保存到文件中吗?答案是没有必要。所有的日志统统送到控制台上面去了。
我们可以直接使用docker container logs xxx或者直接使用docker logs xxx来直接获取一个容器的日志。因为日志只有单个程序运行,没必要非得保存到文件中。而是直接发到控制台去的。
这也是去调试看看容器有没有问题的时候,获取相关信息的一个更加有效的手段。
下一章地址:
Docker容器技术之镜像管理基础(三)