Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

什么是Docker

Docker是一个开源的应用容器引擎,基于Go语言开发的。Docker可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化。

容器是完全使用沙箱机制,相互之间不会有任何接口,更重要的是容器性能开销极低。

Docker和虚拟技术的不同

  • 传统虚拟机,虚拟一套硬件,运行一个完整的操作系统,然后再这个系统上安装和运行软件
  • 容器内的应用直接运行在宿主机的内核,容器是没有自己的内核,也没有虚拟我们的硬件,所以就性能开销比较 小
  • 每个容器间是相互隔离,每个容器都有一个属于自己的文件系统,互不影响

Docker对开发过程中产生的影响

应用更快速的交付和部署

传统:一堆帮助文档,安装程序

Docker:打报镜像,发布测试,一键运行

更便捷的升级和扩缩容

更简单的系统运维

更高效的计算资源利用

Docker安装

docker架构

镜像(image):

docker镜像就好比是一个模板,可以通过这个模板来创建容器服务,tomcat镜像==>run==>tomcat01容器(提供服务),通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在这个容器中)。

容器(conrainer):

Docker利用容器技术,独立运行一个或者一个组应用,通过镜像来创建的。

启动,停止,删除,基本命令

当前为止,我们可以把容器理解为一个简易的linux系统

仓库(repository)

仓库就是存放镜像的地方,仓库分为公有仓库和私有仓库(类似于GitHub)

Docker Hub(默认为国外的仓库)

阿里云等都有容器服务器(配置镜像加速)

安装Docker

Linux:

首先我们进入官网[官网](Get Docker | Docker Documentation),选择Docker For Linux 我们这里是CentOs 所以我们选择这个版本,建议根据官方文档来安装Docker

image-20211014225602394

官方文档建议我们首先卸载旧版本的Docker

1
2
3
4
5
6
7
8
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine

然后安装 yum-utils

1
sudo yum install -y yum-utils

然后设置仓库

1
2
3
sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo

这里建议将仓库地址换成国内仓库

1
2
3
4
5
6
7
8
9
10
Docker中国区官方镜像:
https://registry.docker-cn.com
网易:
http://hub-mirror.c.163.com
ustc:
https://docker.mirrors.ustc.edu.cn
中国科技大学:
https://docker.mirrors.ustc.edu.cn
阿里云:
https://cr.console.aliyun.com/

然后开始运行Docker

1
sudo systemctl start docker

学习开始必不可少 hello world

1
sudo docker run hello-world

当然我们刚开始运行时没有这个镜像的,会从仓库中拉去这个

image-20211014230746375

当我们看见这个的时候说明我们的第一步已经完成了,顺便看一下我们下载的这个镜像

1
docker images

image-20211014231217257

Docker的官方文档可以说是十分的详细了,不仅为我们介绍了怎么安装,同样也为我们说明了怎么卸载docker

image-20211014231416502

Docker 运行原理图

image-20211015140209435

Docker的常用命令

帮助命令

1
2
3
docker version # 查看docker 版本相关信息
docker info #显示docker的系统信息,包括镜像和容器的数量
docker 命令 --help #帮助命令

镜像命令

docker images 查看所有本地的主机上的镜像

1
2
3
4
5
6
7
8
9
10
11
bestrookie@bestrookiedeMac-mini ~ % docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest feb5d9fea6a5 3 weeks ago 13.3kB


#解释
REPOSITORY 镜像的仓库源
TAG 镜像的标签
IMAGE ID 镜像的id
CREATED 镜像的创建日期
SIZE 镜像的大小

docker search搜索镜像

docker pull下载镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#下载镜像 docker pull 镜像名:[版本]
bestrookie@bestrookiedeMac-mini ~ % docker pull mysql #如果不指定tag,默认就是最新的
Using default tag: latest
latest: Pulling from library/mysql
b380bbd43752: Pull complete # 分层下载, docker iamge的核心 联合文件系统
f23cbf2ecc5d: Pull complete
30cfc6c29c0a: Pull complete
b38609286cbe: Pull complete
8211d9e66cd6: Pull complete
2313f9eeca4a: Pull complete
7eb487d00da0: Pull complete
a5d2b117a938: Pull complete
1f6cb474cd1c: Pull complete
896b3fd2ab07: Pull complete
532e67ebb376: Pull complete
233c7958b33f: Pull complete
Digest: sha256:5d52dc010398db422949f079c76e98f6b62230e5b59c0bf7582409d2c85abacb #签名
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest # 真实地址

#等价于它
docker pull mysql
docker pull docker.io/library/mysql:latest

#指定版本下载 指定的版本仓库中一定要有这个版本的镜像
bestrookie@bestrookiedeMac-mini ~ % docker pull mysql:5.7
5.7: Pulling from library/mysql
b380bbd43752: Already exists #其他版本已经存在的不需要再次下载
f23cbf2ecc5d: Already exists
30cfc6c29c0a: Already exists
b38609286cbe: Already exists
8211d9e66cd6: Already exists
2313f9eeca4a: Already exists
7eb487d00da0: Already exists
bb9cc5c700e7: Pull complete
88676eb32344: Pull complete
8fea0b38a348: Pull complete
3dc585bfc693: Pull complete
Digest: sha256:b8814059bbd9c80b78fe4b2b0b70cd70fe3772b3c5d8ee1edfa46791db3224f9
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7

docker rmi 删除镜像

1
2
3
docker rmi -f 镜像id  #删除指定镜像
docker rmi -f 镜像id 镜像id #删除多个镜像
docker rmi -f $(docker images -aq) #删除所有容器

容器命令

我们有了镜像才可以创建容器,我们下载一个centos镜像来测试学习

1
docker pull centos

新建容器并启动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
docker run [可选参数] image

#参数说明
--name ="name" 容器名字 content01 content02 用来区分容器
-d 后台方式运行
-it 使用交互方式运行,进入容器查看内容
-p 指定容器的端口 -p 8080:8080
-p ip:主机端口:容器端口
-p 主机端口:容器端口(常用)
-p 容器端口
容器端口
-P 随机指定端口
# 启动并进入容器
bestrookie@bestrookiedeMac-mini ~ % docker run -it centos
[root@f3bd81d9c682 /]# ls
bin etc lib lost+found mnt proc run srv tmp var
dev home lib64 media opt root sbin sys usr
#从容器中退回主机
[root@f3bd81d9c682 /]# exit

docker ps 列出所有的运行的容器

1
2
3
4
5
6
# docker ps 命令
-a #列出当前正在运行的容器 + 带出历史运行过的容器 如果不加-a就只显示当前运行的容器
-n=? #显示最近创建的容器
-q #只显示容器的编号


退出容器

1
2
3
exit #直接退出容器
ctrl + p + q #容器不停止退出
docker stop id #终止容器运行

删除容器

1
2
docker rm 容器id            #删除指定容器
docker rm $(docker ps -aq) #删除所有容器

启动和停止容器的操作

1
2
3
4
docker start 容器id       #启动容器
docker resatrt 容器id #重启容器
docker stop 容器id #停止当前正在运行的容器
docker kill 容器id #强制停止当前容器

常用其他命令

后台启动容器

1
2
3
4
#命令 docker run -d 镜像名
docker run -d centos
# 问题我们docker ps 发现 centos 停止了
#这是我们经常遇见的一个坑,docker容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止

查看日志

1
docker logs -tf --tail 日志条数(不加查看所有) 容器id

查看容器中进程信息

1
[root@bestrookie bestrookie]# docker top 容器id

image-20211016120746253

查看容器的元数据

1
docker inspect 容器id

进入当前正在运行的容器

1
2
3
4
docker exec -it 容器id bashSell #进入容器后开启一个新的终端,可以在里面操作(常用)
#方式二
docker attch 容器id #进入容器正在执行的终端,不会启动新的进程

将文件拷贝到主机

1
docker cp 容器id:地址 要拷贝到目录

Docker练习 安装nginx

首先我们先搜索在仓库中有没有这个仓库

1
docker search nginx

image-20211016190556133

建议从官网搜索,可以更好的查看版本信息

然后我们下载镜像

1
docker pull nginx

下载完镜像我们创建并运行容器,这里我们可以设置端口号等信息

1
2
docker run -d --name nginx01 -p 3344:80 nginx
# -p 主机端口:docker开启的端口

查看是否成功

image-20211016190945393

image-20211016191043102

我们也可以从浏览器地址访问。

Docker可视化面板

1
2
docker run -d -p 8088:9000 \
> > --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer

Docker镜像

镜像是什么

镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。

所有的应用,直接打包docker镜像,就可以直接跑起来。

如何得到镜像

  • 从远程仓库下载
  • 从别处拷贝
  • 自己制作一个镜像DockerFile

Docker镜像加载原理

UnionFs(联合文件系统)

UnionFs(联合文件系统):UnionFS文件系统是一种分层、轻量级并且高性能的文件系统,他支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。UnionFS文件系统是Docker镜像的基础。镜像可以通过分层来进项集成,基于基础镜像,可以制作各种具体的应用镜像。

特性:椅子同时加载多个文件系统,但从外面开起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终文件系统会包含所有底层的文件和目录

Docker镜像加载原理

docker的镜像实际上由一层层的文件系统组成,这种层级的文件系统UnionFS。

bootfs主要包含BootLoader和kernel,BootLoader主要引导加载kernel,Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们经典的Linux、Unix系统是一样,包括boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。

roofs,在bootfs之上,在bootfs之上。包含的警示典型的Linux系统中的/dev/proc/bin/etc等标准目录和文件。rootfs就是各种不同的操作系统发型版,如Ubuntu,Centos等等。

image-20211016225340471

分层理解

分层的镜像

我们在下载镜像的时候我们发现,镜像是一层一层下载的

分层下载的最大好处就是资源共享,比如多个镜像都从相同的Base镜像构建而来的,那么宿主机只需要在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了,而且镜像的每一层可以被共享。

image-20211016232327447

可以通过docker image inspect 镜像名称查看镜像封层

image-20211016232529332

理解:

所有的Docker镜像都起始于一个基础镜像,当进行修改或增加新的内容是,就会在当前镜像层之上,创建新的镜像层,例如一个基于Ubuntu16.04创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加Python镜像,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。

该镜像当前已经包含三个镜像层

image-20211016232947294

在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下推中举一个简单例子,每个镜像层包含3个文件,而镜像包含了来自两个镜像层的6个文件。

image-20211016233259498

下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有6个文件,这是因为最上层中的文件7是文件5的一个更新版本

image-20211016233512526

这种情况下,上层镜像层中的文件覆盖了底层镜像中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像中。Docker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。

Linux上可用的存储引擎有AUFS、Overlay2、Device Mapper、Btrfs以及ZFS。顾名思义,每种存储引擎都基于Linux中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。

这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。Docker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统.
Linux上可用的存储引擎有AUFS、Overlay2、Device Mapper、Btrfs以及ZFS。顾名思义,每种存储引擎都基于Linux中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。
Docker在Windows 上仅支持windowsfilter一种存储引擎,该引擎基于NTFS文件系统之上实现了分层和CoW[1]。下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图。

下图展示了系统显示相同的三层进行改那个。所有镜像堆叠合并,对外提供统一的视图

image-20211016233954295

特点:Docker镜像层都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部,这一层就是我们常说的容器层,容器之下的都叫镜像层

Commit镜像

1
2
3
docker commit 提交容器成为一个新的副本
#命令和git提交相似
docker commit -m="描述信息" -a="作者信息" 容器id 目标镜像名:版本

容器数据卷

现在我们将镜像打包成一个容器,那么我们将容器删除,我们使用的数据就会丢失,容器数据卷就是为了解决这个问题。容器数据卷就是将我们的容器的文件目录挂载到我们的主机的一个目录上,可以说是实现了双向绑定。

也就是说:容器数据卷实现了容器的持久化同步操作

1
2
3
docker run -it -v 主机目录: 容器内目录
#
docker docker -it -v /home/rookie:/home centos

然后我们使用命令docker inspect查看容器挂载信息

image-20211017121701235

如果挂载信息不对,说明我们没有挂载成功

配置mysql镜像

1
2
docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
#运行容器,需要做数据挂载也就是要实现数据的持久化,否则删掉容器,数据就全部丢失了,并且首次启动容器需要配置登录密码

成功启动以后我们测试一下

在本地用我们的数据库可视化工具链接我们的数据库,并且创建一个数据看看我们挂载文件路径下能否同步。

具名挂载和匿名挂载

匿名挂载

1
2
-v 容器内路径
docker run -d -P --name nginx01 -v /etc/nginx nginx

具名挂载

1
2
-v 卷名:容器内路径
docker run -d -P --name nginx -v nginx01:/etc/nginx nginx

查看所有挂载

1
docker volume ls

初识Dockerfile

Dockerfile就是用来构建docker镜像额构建文件,就是一个命令脚本

通过这个脚本可以生成镜像,镜像是一层一层的,脚本一个一个的命令,每个命令都是一层

1
2
3
4
5
6
7
8
9
10
# 创建一个dockerfile文件,名字可以随机 建议dockerfile
# 文件中的内容 指令(大写) 参数
FROM centos

VOLUME ["volume01","volume02"]

CMD echo "-----end-----"

CMD /bin/bash
# 这里的每个命令,就是镜像的一层

然后通过命令构建

1
docker build -f dockerfile1 -t bestrookie/centos .

运行一下这个容器然后查看容器信息

image-20211017175403415

可以发现已经挂载了我们在,脚本中设置的两个文件,这里使用的匿名挂载

数据卷容器

主要的作用是实现容器中的数据同步。

1
2
docker run -it --name 名称 --volumes-from 父容器名称 镜像
#docker run -it --name docker02 --volumes-from docker01 bestrookie/centos

容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止,但是一旦你持久化到本地,这个时候,本地的数据是不会删除的。

DockerFile

dockerfile是用来构建docker奖项的文件,就是命令脚本

构建步骤:

1、编写一个dockerfile文件

2、docker build 构建成为一个镜像

3、docker run 运行进行镜像

4、docker push 发布镜像

DockerFile构建过程

基础知识:

1、每个保留关键字(指令)都必须是大写字母

2、执行从上到下

3、#表示注释

4、每一个执行都会创建提交一个新的镜像层,并提交

DockerFile的质量

1
2
3
4
5
6
7
8
9
10
11
12
FROM            # 基础镜像,一切从这里开始构建
MAINTAINER #镜像是谁写的,姓名+邮箱
RUN #镜像构建的时候需要运行的命令
ADD #添加镜像
WORKIR #镜像的工作目录
VOLUME #挂载的目录
EXPOSE #保留端口配置
CMD #指定之歌容器启动的时候需要运行的命令,只有最后一个会生效,可以被代替
ENTRUPOINT #指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被代替
ONBUILD #当构建一个被继承的DockerFile这个时候就会运行ONBULID的指令。触发指令
COPY #类似ADD,将我们文件拷贝到镜像中
ENV #构建的时候设置环境变量

实战测试

我们尝试创建一个centos镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 编写DockerFile文件
ENV MYPATH /usr/local
WORKDIR $MYPATH

RUN yum -y install vim
RUN yum -y install net-tools

EXPOSE 80

CMD echo $MYPATH

CMD echo "----end----"

CMD /bin/bash

通过命令构建这个镜像

1
2
docker build -f mydockerfile -t mycentos:1.0 .
# 命令docker build -f dockerfile文件路径 -t 镜像名:[tag]

实战:Tomcat镜像

1、首先准备压缩包

image-20211017211453391

2、编写DockerFile文件,官方命名Dockerfile,build会自动寻找这个文件,无需-f指定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
FROM centos
MAINTAINER bestrookie<bestrookie.qq.com>

COPY readme.txt /usr/local/readme.txt

ADD jdk-8u301-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.54.tar.gz /usr/local/

RUN yum -y install vim
ENV MYPATH /usr/local
WORKDIR $MYPATH

ENV JAVA_HOME /usr/local/jdk1.8.0_301
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.54
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.54

ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin

EXPOSE 8080

CMD /usr/local/apache-tomcat-9.0.54/bin/startup.sh && tail -F /url/local/apache-tomcat-9.0.54/bin/logs/catlina.out

3、构建这个镜像

1
docker build -t diytomcat .

4、运行镜像

1
docker run -d -p 9090:8080 --name bestrookietomcat2 -v /home/bestrookie/rookie/tomcatfile:/usr/local/apache-tomcat-9.0.54/webapps/test -v /home/bestrookie/rookie/logs/:/usr/local/apache-tomcat-9.0.54/logs diytomcat

发布自己的镜像

DockerHub

1、官方仓库注册自己的账号

2、在我们服务器上提交自己的镜像

3、登录账号

1
docker login -u

4、上传镜像

1
docker push

阿里云镜像服务上

1、登录阿里云

2、找到容器镜像服务

3、创建命名空间

4、创建仓库:记得选本地仓库

5、参考官方地址

image-20211017232616378

Docker网络

理解Docker0

首先我们将我们的Dcoker环境清理干净,删除掉所有的镜像和容器,然后查看我们的网络的ip

ip addr

image-20211021214621337

我们发现存在docker0:这样一个地址,这就是为我们分配的docker网络,同样

原理

1、我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个docker0桥接模式,使用的技术是evth-pair技术。

image-20211024223926212

我们再次查看ip 发现图上这个ip

我们发现这个容器带的网卡,都是一对对的,evth-pair就是一对的虚拟设备端口,他们都是成对出现的,一段连着协议,一段彼此相连,正式有这个特性,evth-pair充当一个桥梁,连接各种虚拟网络设备。

正常情况下两个容器可以通过ip来进行网络的联通,但是不可以使用容器的名字进行网络联通,而--link则解决了这个问题

1
2
#例如
docker run -d -P --name tomcat03 --link tomcat02 tomcat

这样我们的tomcat03可以直接ping tomcat02,但是不能反向的ping tomcat02 ping 不通tomcat03,这时因为–link其实就是改了tomcat03host文件,而tomcat02的文件并没有修改,所以无法起作用。

自定义网络

网络模式

桥接模式:就是搭桥访问

none:不配置网络

host:和宿主机共享网络

创建自己的网络

1
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet

使用自己创建的网络

1
docker run -d -P --name tomcat01 --net mynet tomcat

只要使用我们自定义网络的容器,我们不需要--link去连接网络,因为我们自定义的网络docker都已经帮我们维护好对应的关系了。

网络联通

docker network connect 网络名 容器名

连通之后就是将tomcat01 放到了我们定义的网络下,也就是一个容器两个ip

SpringBoot项目打包Dcoker

1、首先创建一个简单的SpringBoot项目。

image-20211026002213755

2、打包应用

3、编写Dockerfile

1
2
3
4
5
FROM java:8
COPY *.jar /app.jar
CMD ["--server.port=8080"]
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]

4、构建镜像

image-20211026002651201

1
docker build -t springdocke .

5、发布运行

1
docker run -d -P --name spring springdocker

评论