Docker
写在前面:本文根据该视频学习编写https://www.bilibili.com/video/BV1og4y1q7M4?p=40
1.Docker概述
Docker简单的讲就是一个虚拟化工具,容器化技术,可以实现快速实现简化服务部署之类的功能,它的核心是
一次构建,到处部署,在通过build以后,会构建完可用的docker镜像,如果以后需要使用或者在别的服务器启动,只需要将镜像发布到远程,通过几行命令拉取镜像,然后根据镜像创建出一个容器,将服务跑起来即可。
1.1 Docker介绍
Docker的意思是码头工人,思想就是"集装箱",表示在物流中简化了运输中多次装货和卸货的时间 ,只需要进行一次封装,节省了大量的资源和时间成本
Docker不像传统的方式一样,只给你打包后的jar包或者war包以及说明安装文档,然后再去根据文档安装环境部署,而Docker是直接给一个docker镜像,这个镜像不仅包含运行的jar包和war包,还有运行服务所依赖的环境,只需要直接拉取镜像,然后创建容器,直接运行就可以。
那么我们现在知道Docker是为了一次构建,到处部署,那么如果只有一台服务器,也不会迁移,只需要部署一次,那么还需要使用Docker吗?如果你确信你的应用都是一次性的,而且只提供给自己使用,那么docker在这种场景下的优势不是特别明显,但是,你真的真的确信,你所做的工作只是一次性的吗?
总结一下Docker带来的好处:
更高效的交付和部署引用:
- 传统:一堆帮助文档,安装运行程序
- Docker:打包镜像发布测试 ,只需几条命令
更便捷的升级和扩展:
- 要增加服务器?打包镜像分分中扩展一个服务器
更高效的计算资源利用:
- Docker是内核级别的虚拟机化,可以在一个物理机运行很多个容器实例,可以将服务器的性能提高到最佳
参考:Docker是什么?
1.2 Docker组成

镜像(Images):
镜像就是一个模版,可以通过镜像构建多个容器,镜像不可以直接运行的,避免在运行中或者配置中损坏,最终服务运行或者项目运行就是在容器中运行的
容器(Container):
Docker利用容器技术,由镜像创建容器,独立运行一个或者一组应用,每个容器由自己的专用文件系统,通过命令启动、停止、删除应用等!
仓库(Registry):
仓库就是存放镜像的地方,分为共有仓库和私有仓库,镜像就是从仓库下载的
默认使用的是Docker Hub(国外的)下载很慢,可以使用国内的仓库,比如阿里云...
1.3 Docker为什么比虚拟机快
1.Docker不需要硬件资源虚拟化,运行在Docker容器上的应用直接使用的物理机资源,所以在内存、CPU上比虚拟机的利用率更高
2.Docker利用的是宿主机的内核,当新建一个容器的时候,不需要和虚拟机一样重新加载操作系统,省去了大量的时间
2.Docker安装
2.1 开始安装
1.卸载旧的版本
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
2.下载需要的安装包
sudo yum install -y yum-utils
3.设置镜像存储库
#这是国外的,下载很慢
sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
#这是阿里云的,推荐
sudo yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
4.安装的Docker引擎、客户端、容器;ce是社区版,ee是企业版,官方推荐使用社区版
#安装最新版本
sudo yum install docker-ce docker-ce-cli containerd.io
#安装指定版本
#1.列出可用版本
yum list docker-ce --showduplicates | sort -r
docker-ce.x86_64 3:18.09.1-3.el7 docker-ce-stable
docker-ce.x86_64 3:18.09.0-3.el7 docker-ce-stable
docker-ce.x86_64 18.06.1.ce-3.el7 docker-ce-stable
docker-ce.x86_64 18.06.0.ce-3.el7 docker-ce-stable
#2.通过软件包的名称+版本字符串进行安装 VERSION_STRING:第二列第一个:一直到-前的字符,比如18.09.1
sudo yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io
5.启动Docker
sudo systemctl start docker
6.测试是否安装成功
docker version
7.运行hello-world
sudo docker run hello-world

run的执行流程:

8.查看下载的镜像
docker images
9.卸载Docker
#1.卸载Docker Engine,CLI和Containerd软件包:
sudo yum remove docker-ce docker-ce-cli containerd.io
#2.删除主机上的映像,容器,卷或自定义配置文件 /var/lib/docker:docker的默认工作路径
sudo rm -rf /var/lib/docker
2.1 阿里云镜像加速器
因为很多镜像在国外,下载非常慢,配上加速器会更快
阿里云官网容器镜像地址:https://cr.console.aliyun.com/cn-beijing/instances/mirrors
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://e859w42o.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
3.常用命令
3.1 镜像命令
查看本地主机上的所有镜像
$ docker images [-a] [-q]
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest bf756fb1ae65 5 months ago 13.3kB
# 解释
REPOSITORY:镜像名称
TAG:镜像版本
IMAGE ID:镜像ID
CREATED:镜像创建时间
SIZE:镜像大小
# 可选项
-a,--all:列出所有镜像
-q,--quiet:只显示镜像ID
搜索镜像
镜像搜索网址:https://hub.docker.com/
$ docker search imagename
# 搜索mysql
$ docker search mysql [--limit]
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 9574 [OK]
mariadb MariaDB is a community-developed fork of MyS… 3478 [OK]
# 可选项
--limit 5:只显示前5条镜像
--filter=stars=3000:只显示stars大于3000的镜像
下载镜像
$ docker pull imagename[:tag]
# 下载mysql
$ docker pull mysql
Using default tag: latest #默认下载最新版
latest: Pulling from library/mysql
afb6ec6fdc1c: Pull complete #分层下载,它下载过以后,下载其他mysql镜像版本时重复的就不需要下载了
0bdc5971ba40: Pull complete
97ae94a2c729: Pull complete
f777521d340e: Pull complete
1393ff7fc871: Pull complete
a499b89994d9: Pull complete
7ebe8eefbafe: Pull complete
597069368ef1: Pull complete
ce39a5501878: Pull complete
7d545bca14bf: Pull complete
211e5bb2ae7b: Pull complete
5914e537c077: Pull complete
Digest: sha256:a31a277d8d39450220c722c1302a345c84206e7fd4cdb619e7face046e89031d
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest #mysql的真实地址
# 下载mysql5.7版本的,版本号必须是存在才可以下载,如果下载99.99版本肯定会报错找不到的
$ docker pull mysql:5.7
删除镜像
$ docker rmi -f IMAGE ID
# 根据镜像ID删除镜像
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql 5.7 a4fdfd462add 12 days ago 448MB
mysql latest 30f937e841c8 12 days ago 541MB
hello-world latest bf756fb1ae65 5 months ago 13.3kB
$ docker rmi -f a4fdfd462add
# 根据镜像ID删除多个镜像
docker rmi -f a4fdfd462add 30f937e841c8
# 删除全部镜像,意思就是先查询出来所有的ID,然后全部删除
$ docker rmi -f $(docker images -aq)
3.2 容器命令
说明:有了镜像才可以创建容器,下载一个centos镜像来学习
$ docker pull centos
新建容器并启动
$ docker run [可选项] imagename
# 可选项
--name : 容器名字
-d. : 以后台方式运行
-it : 进入容器
-p : 指定容器端口
-p 主机端口:容器端口(常用)
# 启动并进入容器
$ docker run -it centos
退出容器
# 退出并停止容器
$ exit
# 退出但不停止容器
Control + P + Q
查看容器状态
$ docker ps [-a] [-q]
# 查看当前运行的容器
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
64ac46420f91 centos "/bin/bash" 14 seconds ago Up 13 seconds vigorous_ishizaka
# 查看所有的容器
$ docker ps -a
# 查看所有的容器ID
$ docker ps -aq
删除容器
$ docker rm [-f] containerId
# 根据ID删除指定的容器
$ docker rm 64ac46420f91
# 删除全部容器
$ docker rm -f $(docker ps -aq)
# 可选项
-f :强制删除,运行中的容器不能直接删除,需要-f参数
启动和停止容器
docker start containerID #启动容器
docker restart containerID #重启容器
docker stop containerID #停止当前运行中的 容器
docker kill containerID #强制停止当前容器
3.3 其他命令
查看日志
$ docker logs [-t] [-f] [--tail num] containerID
# 可选项
-t : 显示时间戳
-f : 跟踪显示日志
--tail num:显示num行日志
# 跟踪查看全部日志
docker logs -tf containerID
查看当前容器的元数据信息
$ docker inspect containerID
进入容器
# 进入后开启一个新的终端
$ docker exec -it containerID /bin/bash
# 进入容器正在执行的终端
$ docker attach containerID
将容器中的文件拷贝到主机上
$ docker cp containerID:容器文件路径 主机路径
eq:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS
51c13cc979ed centos "/bin/bash" 4 minutes ago Up 1
# 1.进入容器
$ docker exec -it 51c13cc979ed /bin/bash
# 2.在容器创建一个文件
$ touch /home/test.java
# 3.退出容器
$ exit
# 4.将容器中的test.java拷贝到主机的/home下
$ docker cp 51c13cc979ed:/home/test /home
3.4 安装Nginx
# 1.搜索镜像
$ docker search nginx
# 2.下载nginx镜像
$ docker pull nginx
# 3.新建容器并启动
$ docker run -d --name nginx01 -p 3344:80 nginx
3.5 安装Tomcat
# 1.搜索镜像
$ docker search tomcat
# 2.下载tomcat9.0版本的镜像
$ docker pull tomcat:9.0
# 3.新建容器并启动,后面需要添加版本
$ docker run -d --name tomcat01 -p 8080:8080 tomcat9.0
# 4.启动后浏览器访问http://ip:8080会出现404,这是因为tomcat的webapps目录下默认没有内容,需要将webapps.dist目录下的文件拷贝到webapps目录
$ docker exec -it 容器id /bin/bash
$ cp -r webapps.dist/* webapps
# 然后再访问就出现了tomcat默认页面
-d:在后台启动—name:容器名字为nginx01-p:指定端口映射,在浏览器访问 http://ip:3344会映射到80端口
为什么需要端口映射呢?
这是外网可以访问Linux,而Linux无法直接访问Docker,需要进行一个端口映射才可以访问

3.6 可视化面板
Portainer是Docker的图形化管理工具,提供状态显示面板、应用模板快速部署、容器镜像网络数据卷的基本操作(包括上传下载镜像,创建容器等操作)、事件日志显示、容器控制台操作、Swarm集群和服务等集中管理和操作、登录用户管理和控制等功能。功能十分全面,基本能满足中小型单位对容器管理的全部需求。
首先下载Portainer镜像
# 下载镜像
$ docker pull docker.io/portainer/portainer
然后启动Portainer
$ docker run -d -p 9000:9000 \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
--name prtainer-test \
docker.io/portainer/portainer
启动成功,访问http://IP:9000
第一次登录会先创建账户

如果只有一个Docker宿主机就选择Local,Docker集群选择Remote

然后会进入主页面,可以查看容器、镜像、并进行启动删除等操作

4.Docker镜像
4.1镜像原理
镜像是一个轻量级、可执行的软件包,用来打包软件以及它的运行环境,包含代码、环境、配置文件等内容
Docker镜像加载原理
docker镜像实际是由一层一层的文件系统构成的,叫做联合文件系统,以pull为例,当下载镜像的时候,会发现是一层一层的进行下载,这样做的好处就是共享资源,因为多个镜像可能都从相同的base镜像构建而来,那么宿主机只需要保存一份镜像,就可以为所有镜像服务了
docker是只读的,当运行的时候,会构建一个可写层,也就是容器层,所有的操作都是对于容器层的
4.2 Commit镜像
# 提交容器成为一个新的镜像
$ docker commit -a="作者" -m="提交信息" 容器id 镜像名:[TAG]
比如docker下载下来的tomcat镜像默认访问是404的,还需要进行一个拷贝才可以访问,那我们就可以将我们第一次拷贝后的容器进行提交,提交成一个新的镜像,下次运行的时候直接运行这个提交后的镜像即可
5.容器数据卷
5.1 什么是容器数据卷
我们知道,数据都是保存在容器中,那如果容器删除,数据也就会丢失!比如MySQL,当容器删除,那它的配置文件以及数据库信息都会被删除,这无疑是要命的。
那如何保证数据不会丢失,将数据持久化到主机就是容器数据卷技术所做的事情,将容器的目录与主机的目录进行挂载,文件会自动完成同步。
有了容器数据卷,对于Nginx的配置文件就不需要每次修改都进入容器,可以在主机中创建一个文件与Nginx配置文件挂载,然后直接修改主机的文件即可。
5.2 使用数据卷
-v:直接使用使用命令来挂载
$ docker run -d -v 主机路径:容器路径 imagename
# 测试,将主机的/home/ceshi与centos容器的/home目录挂载
$ docker run -it -v /home/ceshi:/home centos /bin/bash
# 挂载以后,可以使用命令查看是否挂载成功
$ docker inspect 容器ID

无论是添加、删除、修改文件都会进行同步,如果需要删除容器,那么当下次新建容器并启动的时候通过-v命令进行挂载还是会进行同步。
5.3 安装MySQL
# 下载MySQL
[root@aliyun ~]# docker pull mysql:5.7
# 启动mysql
-d : 后台启动
--name :容器命名
-p :端口映射
-v :挂载MySQL的配置文件和数据目录
-e :设置全局变量,MYSQL_ROOT_PASSWORD:mysql root用户密码
$ docker run -d --name mysql01 -p 3306:3306 -v /home/mysql/conf:/etc/conf.d -v /home/mysql/data:/var/lib/data -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
使用数据库连接工具连接测试,并且新建一个数据库会发现主机的/home/mysql/data目录也会新增一个目录就是新建的数据库,这样即使容器删除,数据库信息也不会丢失。
5.4 具名挂载和匿名挂载
除了指定路径挂载,还有不指定路径挂载,不指定路径挂载分为两种,具名挂载和匿名挂载
# 匿名挂载:只需指定容器内的路径
-v 容器路径
# 具名挂载:卷名:容器路径(常用,可以很方便的找到卷)
-v 卷名:容器路径
# 查看所有的卷情况
[root@aliyun ~]# docker volume ls
DRIVER VOLUME NAME
# 这种就是匿名挂载
local 38e923e0eb2c97b615da006ebe828fa79beb428bd9690d8d9291fafd7f35e63a
# 具名挂载,以启动nginx为例
[root@aliyun ~]# docker run --name nginx01 -P -d -v juming-nginx:/etc/nginx nginx
# 在查看所有的卷情况
[root@aliyun ~]# docker volume ls
DRIVER VOLUME NAME
local 38e923e0eb2c97b615da006ebe828fa79beb428bd9690d8d9291fafd7f35e63a
local juming-nginx #这种就是具名挂载
# 查看具体的卷情况
[root@aliyun ~]# docker volume inspect juming-nginx
[
{
"CreatedAt": "2020-06-04T09:14:41+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data",
"Name": "juming-nginx",
"Options": null,
"Scope": "local"
}
]
# 所有没有指定目录的容器中的卷,都存在/var/lib/docker/volumes/目录下
拓展,挂载后操作文件的权限:
# ro 与 rw
# 如果在-v容器路径后面添加ro,代表这个路径只能通过宿主机进行操作,容器只能读,不能修改
[root@aliyun ~]# docker run --name nginx01 -P -d -v juming-nginx:/etc/nginx:ro nginx
# 当你尝试去修改文件或者删除等操作时,会提示 Read-only file system
root@dbf2edeab1e0:/etc/nginx# rm -f nginx.conf
rm: cannot remove 'nginx.conf': Read-only file system
# 如果在-v容器路径后面添加rw,容器可读可写
[root@aliyun ~]# docker run --name nginx01 -P -d -v juming-nginx:/etc/nginx:rw nginx
6.DockerFile
DockerFile是用来
构建Docker镜像的文件,一个命令脚本,通过脚本可以生成镜像
6.1 DockerFile构建过程
1.编写一个dockerfile文件
2.docker build 构建一个镜像
3.docker run 运行镜像
4.docker push 发布镜像到仓库
首先,定义一个DockerFile脚本
FROM centos
# 挂载容器目录,匿名挂载
VOLUME ["volume01","volume02"]
CMD echo "---end---"
CMD /bin/bash
然后,用命令通过脚本构建出一个镜像
# docker build -f 脚本路径 -t 镜像名称 . 小数点不要忘记写
[root@aliyun ~]# docker build -f dockerfile01 -t dingjn/centos0 .
# 查看生成的镜像
[root@aliyun docker-test-volume]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
dingjn/centos latest a62f2759bc90 5 minutes ago 237MB
# 查看挂载的目录,这就是volume01和volume02挂载的目录,属于匿名挂载
[root@aliyun ~]# docker volume ls
DRIVER VOLUME NAME
local 0ca3a36c0d38ac06941173bd3a98c2d3750f11ac4a8c48b1609da933c6048bf9
local e44535e081df4011333688be151fdaaf252877f17e4f06cabe4b76528c94f0ba
# 查看挂载的具体信息
[root@aliyun ~]# docker volume inpect 0ca3a36c0d38ac.....
# 然后测试是否同步
6.2 DockerFile指令
通过这些指令来编写一个构建镜像的脚本!
FROM # 指定基础镜像,指基于哪个镜像构建的,centos、Ubonto、windows....
MAINTAINER # 镜像是谁写的,姓名+邮箱
RUN # 镜像构建时执行的命令
ADD # 添加文件,并且会自动将文件解压
WORKDIR # 镜像的工作目录
VOLUME # 挂载目录
EXPOSE # 端口配置
CMD # 容器启动时执行的命令,会覆盖
ENTRYPOINT # 容器启动时执行的命令。会追加
COPY # 将文件拷贝到镜像中,不会自动解压
ENV # 构建的时候设置环境变量,比如mysql的MYSQL_ROOT_PASSWORD
CMD和ENTRYPOINT的区别
测试,
# 1.首先编写一个测试cmd的dockerfile文件,叫做dockerfile-cmd-test
FROM CENTOS
CMD ["ls","-a"]
# 2.构建镜像
docker build -f dockerfile-cmd-test -t cmdtest .
# 3.运行镜像
docker run cmdtest
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
# 4.运行时添加参数
docker run cmdtest -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"-l\": executable file not found in $PATH": unknown.
#提示错误,这是因为-l会替换掉["ls","-a"]
#而如果将dockerfile中的CMD替换成ENTRYPOINT,就不会报错,因为会追加为["ls","-a","-l"]
6.3 实战测试
构建一个centos镜像
1.编写dockerfile文件
# 基于centos镜像构建
FROM centos
# 作者信息
MAINTAINER dingjn<codedjn@163.com>
# 环境变量
ENV MYPATH /usr/local
# 工作目录
WORKDIR $MYPATH
# run时下载vim和net-tools
RUN yum -y install vim
RUN yum -y install net-tools
# 暴露端口
EXPOSE 80
# 运行容器时执行
CMD echo $MYPATH
CMD echo "---end---"
CMD /bin/bash
2.构建
docker build -f mydockerfile -t mycentos .
6.4 发布镜像
发布到DockerHub
1.在DockerHub注册自己的账号
2.开始提交镜像
# 1.登录,注册的账号和密码
[root@aliyun ~]# docker login -u dingjn
Password:
....
Login Succeeded
# 2.开始push,自己发布的镜像带上版本号
[root@aliyun ~]# docker push dingjn/centos:1.0
发布到阿里云镜像仓库
1.进入阿里云镜像地址
2.创建命名空间

3.创建镜像仓库


4.开始上传:
# 登录
$ sudo docker login --username=java丁江楠hh registry.cn-hangzhou.aliyuncs.com
# 修改镜像添加版本号
$ sudo docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/djn-basic/test:[镜像版本号]
#推送
$ sudo docker push registry.cn-hangzhou.aliyuncs.com/djn-basic/test:[镜像版本号]
如果出现denied: requested access to the resource is denied,是因为镜像名称不对,需要使用registry.cn-hangzhou.aliyuncs.com/djn-basic/test作为前缀,替换为自己的命名空间+镜像仓库名称
7.整合Springboot
# 1.首先创建一个Springboot项目,然后打成jar包 --- demo.jar
# 2.编写DockerFile文件 ---DockFile
FROM java:8
COPY *.jar /app.jar
CMD ["--server.port=8080"]
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]
CMD echo "---end---"
# 3.将jar包和文件传输到服务器
# 4.然后执行dockerbuild命令执行DockerFile文件打成镜像
docker build -t demo .
# 5.docker run运行镜像
docker run demo
# 6.如果需要将镜像给别人运行,就发布到阿里云
sudo docker login --username=java丁江楠hh registry.cn-hangzhou.aliyuncs.com
sudo docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/djn-basic/test/demo:1.0
sudo docker push registry.cn-hangzhou.aliyuncs.com/djn-basic/test/demo:1.0

浙公网安备 33010602011771号