内容根据B站《Docker最新超详细版教程通俗易懂》课程制作
文章目录
前言
镜像(image)
Docker镜像就好比是一个模板,可以通过这个模板来创建容器服务, 通过这个镜像可以创建多个容器,最终服务运行或者项目运行就是在容器中的容器(container)
Docker利用容器技术,独立运行一个或者一组应用, 通过镜像来创建的
启动,停止,删除,基本命令!仓库(repository)
存放镜像的地方
Docker Hub(默认是国外的)
阿里云,都有容器服务(配置镜像加速!)
以下是本篇文章正文内容
一、安装Docker
1.1 卸载旧版本
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
1.2 需要的安装包
yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
1.3 设置镜像仓库
- 阿里云镜像
yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
- 官方源地址(速度较慢)
yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
1.4 安装Docker相关内容
- 更新yum软件包索引
yum makecache fast
- 安装最新版本的 Docker Engine-Community 和 containerd,或者转到下一步安装特定版本:
yum install docker-ce docker-ce-cli containerd.io
- docker-ce:代表社区版
- 安装成功
docker version
- 配置阿里云镜像服务
在阿里云官网的控制台中,找到容器镜像服务->镜像工具->镜像加速器
找到以下代码,在/etc/docker/daemon.json中加入镜像网址
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://niphmcik.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
1.5 启动 Docker
$ sudo systemctl start docker
通过运行 hello-world 映像来验证是否正确安装了 Docker Engine-Community 。
$ sudo docker run hello-world
1.6 删除Docker
- 卸载依赖
yum remove docker-ce docker-ce-cli containerd.io
- 删除资源
rm -rf /var/lib/docker # docker默认的工作路径
1.7 Docker的run工作流程
二、 Docker的基本命令
2.1 帮助命令
# 帮助命令
docker version # 显示docker的版本信息
docker info # 显示docker的系统信息,包括镜像和容器的数量
docker 命令 --help # 帮助命令
帮助文档的地址:docker build | Docker Documentation
2.2 镜像命令
获取镜像:
从远程仓库下载
自己制作一个镜像 DockerFile
docker images //显示镜像信息
# 可选项
# -a, --all # 列出所有镜像
# -q, --quiet # 只显示镜像的ID
- REPOSITORY 镜像的仓库源
- TAG 镜像的标签
- IMAGE ID 镜像的ID
- CREATED 镜像的创建时间
- SIZE 镜像的大小
docker search 镜像名称 #搜索镜像
docker pull 镜像名称:版本号 # 下载镜像,不写版本号默认最新
docker rmi 删除镜像
docker rmi -f 镜像ID # 删除指定的镜像
docker rmi -f 镜像ID 镜像ID 镜像ID... # 删除多个镜像
docker rmi -f $(docker images -aq) # 删除全部的镜像
2.3 commit 提交镜像
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG](版本)
三、 容器命令
有了镜像才可以创建容器
比如下载一个centos镜像
docker pull centos
# 1,启动一个默认的tomcat
# 2,进入容器,对这个容器进行修改
# 3,将我们操作过的容器通过commit提交为一个镜像!我们以后就使用我们修改过的镜像即可,这就是我们自己的一个修改的镜像。
docker commit -a="author" -m="add webapps app" 7e119b82cff6 tomcat02:1.0
# 4,通过docker images即可查看提交的镜像,这就相当于VM的快照
3.1 新建容器
docker run [可选参数] imageName
# 参数说明
--name="Name" # 容器名字 例如tomcat01 tomcat02,用来区分容器
-d # 后台方式运行
-it # 使用交互方式运行,进入容器查看内容
-P # 指定容器的端口
-P ip:主机端口:容器端口
-P 主机端口:容器端口 #(常用,这是映射方式)如-P 8080:8080(与主机映射方式)
-P 容器端口
容器端口
-p # 随机指定端口
-v # 使用数据卷挂载,详见第六章
常见的坑,docker 容器运行,就必须要有一个前台进程(比如-it进入交互),docker发现没有应用,就会自动停止
nginx, 容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了
# 测试,启动并进入容器
[root@centos ~]# docker run -it centos /bin/bash
[root@16f4ee728cb6 /]#
3.2 启动和停止容器的操作
docker start 容器id # 启动容器
docker restart 容器id # 重启容器
docker stop 容器id # 停止当前正在运行的容器
docker kill 容器id # 强制停止当前容器
3.3 退出容器
exit # 直接容器停止并退出
快捷键Ctrl + p + Q # 容器不停止退出
3.4 列出运行的容器
docker ps 命令
#列出当前正在运行的容器
-a #列出当前正在运行的容器+顺带带出历史运行过的容器
-n=num(参数) # 显示最近创建的num个容器
-q # 只显示容器的编号
3.5 删除容器
docker rm 容器id # 删除指定的容器,不能删除正在运行的容器,如果要强制删除要rm -f
docker rm -f $(docker ps -aq) # 删除所有的容器
docker ps -a -q|xargs docker rm #删除所有的容器
四、 其它命令
- 查看日志
docker logs -tf [--tail num] 容器ID
# --tail num 要显示的日志条数,没有此参数则显示全部
- 查看容器内的进程信息
docker top 容器id
- 查看镜像的元数据
docker inspect 容器id
镜像的元数据是指与镜像相关的所有信息,包括镜像的名称和标签、作者、描述、创建日期、环境变量、命令等。
- 进入当前正在运行的容器
我们通常容器都是使用后台方式运行的,需要进入容器,修改一些配置
# 方式一
docker exec -it 容器id bashShell(/bin/bash)
# 方式二
docker attach 容器id
# 区别
# docker exec # 进入容器后开启一个新的终端,可以在里面操作(常用)
# docker attach # 只是进入容器正在执行的终端,不会启动新的进程!
- 查看docker的cpu状态
docker stats
- 从容器内拷贝文件到主机上
docker cp 容器id:容器内路径 目的的主机路径
# 拷贝是一个手动过程,未来我们使用 -v 卷的计数,可以实现 自动同步
五、 Docker创建容器示例
Docker 安装 Nginx
- 搜索镜像 search 建议去docker搜索,可以看到帮助文档信息
- 下载镜像 docker pull nginx
- 运行测试 docker images
- 后台启动,命名容器位nginx01,映射主机端口位3344
docker run -d --name nginx01 -p 3344:80 nginx
- 查看状态 docker ps
- 进入容器 docker exec -it nginx01 /bin/bash
- 外网访问
六、 容器数据卷
挂载(mounts):指的就是将设备文件中的顶级目录连接到 Linux 根目录下的某一目录(最好是空目录),访问此目录就等同于访问设备文件。
卷技术:就相当于目录的挂载,将我们容器内的目录,挂载在Liunx上面!
目的:容器的持久化和同步操作,将容器的数据、目录同步到主机中。
容器间也是可以数据共享的
6.1 使用数据卷
方式一:直接使用命令来挂载 -v(第二种在Dockerfile中)
docker run -it -v 主机目录:容器内目录 镜像name /bin/bash
# 主机目录和容器目录的内容自动互相同步
docker run -it -v 主机目录:容器内目录 -v 主机目录2:容器内目录2.. 镜像name /bin/bash
# 可以映射多个目录
# 测试
docker run -it -v /home/ceshi:/home centos /bin/bash
修改只需要在本地修改即可,容器内会自动同步!
清理无主的数据卷
docker volume prune
6.2 Mysql实例
获取镜像 docker pull mysql:5.7
启动MySQL,注意需要配置密码!
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-d 后台运行
-p 端口映射,暴露端口
-v 卷挂载
-e 环境配置
– name 容器名字主机使用Navicat测试连接
连接成功后,在Navicat中进行数据库操作,会同步到主机的/home/mysql/data目录下
将容器删除后,这些同步的数据也不会删除
6.3 具名和匿名挂载
# 查看所有的 volume 的情况
docker volume ls
-v 容器内路径 # 匿名挂载
-v 卷名:容器内路径 # 具名挂载(就是有个名字)
-v /宿主机路径:容器内路径 # 指定路径挂载!
匿名挂载
docker run -d -P --name nginx01 -v /etc/nginx nginx #此为容器内目录
这里发现,这种就是匿名挂载,我们在 -v 只写了容器内的路径,没有写容器外的路径!
具名挂载(常用)
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
# 通过 -v 卷名:容器内路径,实现具名挂载
-v juming-nginx:/etc/nginx
中,juming-nginx即为挂载name,后续为容器内目录
查看挂载信息
docker volume inspect VOLUME NAME(挂载名)
# 示例
docker volume inspect juming-nginx
所有的docker容器内的卷,没有指定目录的情况下都是在./var/lib/docker/volumes/xxxxxx/_data
通过具名挂载可以方便的找打我们的 卷,大多数情况在使用的具名挂载
拓展
# 通过 -v 容器内路径: ro rw 改变读写权限
ro readonly # 只读,这个路径只能通过宿主机来操作,容器内部无法操作
rw readwrite # 可读可写
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx
七、 Dockerfile
Dockerfile 就是用来构建 docker 镜像的构建文件
DockerFile:构建文件,定义了一切的步骤,源代码
Dockerimages:通过DockerFile 构建生成的镜像,最终发布和运行的产品!
Docker容器:容器就是镜像运行起来提供服务器
7.1 构建步骤
- 编写一个dockerfile 文件
- 每个保留关键字(指令)都是必须是大写字母
- 执行从上到下顺序执行
- #表示注释
- 每一个指令都会创建提交一个新的镜像层,并提交!
- docker build 构建成为一个镜像
- docker run 运行镜像
- docker push 发布镜像 (Docker Hub,阿里云镜像仓库!)
7.2 基础命令
FROM # 基础镜像,一切从这里开始构建
MAINTAINER # 镜像是谁写的,姓名+邮箱
RUN # 镜像构建(build)的时候需要运行的命令
ADD # 步骤:tomcat镜像,这个tomcat压缩包!添加内容
WROKDIR # 镜像的工作目录
VOLUME # 挂载的目录
EXPOSE # 暴露端口配置
CMD # 指定这个容器启动(run)的时候要运行的命令,只有最后一个会生效,可被替代
# 比如执行命令:docker run cmdtest -l ,想追加-l时,-l会替代dockerfile文件中的cmd命令,而不是追加
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
# 比如执行命令:docker run entrypointtest -l ,想追加-l时,-l会追加到dockerfile文件中的entrypoint命令之后一起执行
ONBUTLD # 当构建一个被继承 DockerFile 这个时候就会运行 ONBUTLD 的指令,出发指令
COPY # 类似ADD,将我们文件拷贝到镜像中
ENV # 构建的时候设置环境变量
99%镜像都是从这个基础镜像过来的FROM scratch
,然后配置需要的软件和配置来进行的构建
创建自定义centos镜像示例
- 编写dockerfile文件
cat mydockerfile-centos
FROM centos:7
MAINTAINER xxx<xxx@qq.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum -y install vim # 添加vim命令的相关配置
RUN yum -y install net-tools # net-tools相关
EXPOSE 80
CMD echo $MYPATH
CMD echo "------end------"
CMD /bin/bash
- 通过这个文件构建镜像
命令 docker build -f dockerfile文件路径 -t 镜像命:[tag]
docker build -f mydockerfile-centos -t mycentos:0.1 .
# docker build 最后的 . 号,是在指定镜像构建过程中的上下文环境的目录
在Dockerfile中挂载示例
我们可以在Dockerfile中使用VOLUME指令来给镜像添加一个或多个数据卷。
下面使用Dockerfile构建一个新的镜像,dockerfile01文件的内容,匿名挂载了volume01和volume02两个目录:(方式二挂载)
FROM centos # 指定基础镜像
VOLUME ["volume01","volume02"] # 挂载目录
CMD echo "----end----" # 指定这个容器启动的时候要运行的命令,只有最后一个CMD会生效
CMD /bin/bash
执行构建镜像
docker build -f /home/docker-test-volume/dockerfile01 -t mycentos .
# docker build 最后的 . 号,是在指定镜像构建过程中的上下文环境的目录
完成镜像的生成后,启动自己生成的容器
docker images # 查看镜像ID
docker run -it 镜像ID /bin/bash
ls # 可以查看到挂载目录volume01和volume02
因为dockerfile中没有指定宿主机目录,所以属于匿名挂载,在/var/lib/docker/volumes/目录下生成了随机命名的路径。
发布镜像
登录阿里云
在工作台找到容器镜像服务ACR
需要创建个人实例,创建命名空间,命名空间就是镜像列表的上级目录(命名空间个人只能创建3个)
创建容器镜像仓库,仓库名称也就是你的镜像名称,里面装的此镜像的各个版本
点击仓库名称,查看仓库相关信息及pull和push步骤
登陆->修改镜像名称->push
docker login --username=登陆名 registry.cn-hangzhou.aliyuncs.com
docker tag 5d0da3dc9764 registry.cn-hangzhou.aliyuncs.com/命名空间/centos:2.0
docker push registry.cn-hangzhou.aliyuncs.com/命名空间/centos:2.0
- 在镜像版本中查看上传此镜像的各个版本
八、 数据卷容器
容器数据卷是指建立数据卷,来同步多个容器间的数据,实现容器间的数据同步
首先启动容器1,volume01、volume02为挂载目录。
docker run -it --name cnetos01 mycentos
然后启动容器2,通过参数–volumes-from,设置容器2和容器1建立数据卷挂载关系。 此时,容器1也成为数据卷容器。
docker run -it --name centos02 --volumes-from cnetos01 mycentos
在容器2中的volume01中添加文件 ,然后就可以看到容器1的文件也会添加上了
总结:容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止。
但是一但你持久化到了本地,这个时候,本地的数据是不会删除的!
示例
下面同步两个MySQL的数据库和配置文件,与上面的操作相同,首先建立数据卷,然后给另一个MySQL容器建立容器数据卷挂载,示例:
docker run -d -p 6603: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
docker run -d -p 6604:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7
九、 Docker网络
9.1 Docker0网络通信
我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个网卡docker0桥接模式,使用的技术是evth-pair技术!(可以在docker容器中用ip addr
查看)
在容器中,使用ip addr
查看,还有一个veth网卡,是一对两个接口,一端连着协议,一端彼此相连。
正因为有这个特性,evth-pair 充当一个桥梁,连接各种虚拟网络设备的
如下图,tomcat01向tomcat02通信,并不是直接通信,而是经过Docker0网进行间接通信,Docker0就充当的是路由器角色
Docker 中的所有的网络接口都是虚拟的,虚拟的转发效率高!(内网传递文件)
9.2 link(不推荐使用,推荐用自定义网络)
思考一个场景,我们编写了一个微服务,database url=ip:,项目不重启,数据库ip换掉了,我们希望可以处理这个问题,可以用名字来访问容器
docker exec -it tomcat02 ping tomcat01 # 直接ping是不通的
# ping: tomcat01: Name or service not known
# 如何解决
docker run -d -P --name tomcat03 --link tomcat02 tomcat
docker exec -it tomcat03 ping tomcat02 # ping通
# 反向不可以ping通,反向也需要配置--link
docker exec -it tomcat02 ping tomcat03
# ping: tomcat03: Name or service not known
–link 就是我们在hosts配置中增加了一些如172.18.0.3 tomcat02,即域名映射
9.3 自定义网络
docker0是默认的,域名不能访问, 但 --link可以打通连接!
可以自定义一个网络!
# --subnet 192.168.0.0/16
# --gateway 192.168.0.1
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
# 定义了一个192.169.0.0/16的局域网
查看网络配置
docker network ls
NETWORK ID NAME DRIVER SCOPE
c699015536d2 bridge bridge local
195ae44fa95a host host local
7deef8178eef mynet bridge local
82568a72415c none null local
启动两个docker容器
docker run -d -P --name tomcat-net-01 --net mynet tomcat # 指定网络
docker run -d -P --name tomcat-net-02 --net mynet tomcat
# 指定网络后,就会分配该局域网下的ip地址
此时可以互相ping通
docker exec -it tomcat-net-01 ping 192.168.0.3
docker exec -it tomcat-net-01 ping tomcat-net-02
# 用名字也可以,因为指定网络时,会自动在mynet配置中增加域名映射
优点:不同的集群使用不同的网络,保证集群是安全和健康的
9.4 网络连通
不同自定义网络的容器是不能通信的
可以通过连接网络进行通信
docker network connect 网络名 容器名
# 将容器和网络连通
# 示例,将tomcat01和mynet连通,实质就是将tomcat01放在了mynet网络下,一个容器两个IP
docker network connect mynet tomcat01
十、 部署Redis集群
建立三主三从集群
- 设置redis网络
docker network create redis --subnet 172.38.0.0/16
docker network ls # 查看网络列表
- 通过脚本创建六个redis配置
for port in $(seq 1 6); \
do \
mkdir -p /mydata/redis/node-${port}/conf
touch /mydata/redis/node-${port}/conf/redis.conf
cat << EOF >>/mydata/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done
- 逐个开启六个redis容器
docker run -p 6371:6379 -p 16371:16379 --name redis-1 \
-v /mydata/redis/node-1/data:/data \
-v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
docker run -p 6372:6379 -p 16372:16379 --name redis-2 \
-v /mydata/redis/node-2/data:/data \
-v /mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
docker run -p 6373:6379 -p 16373:16379 --name redis-3 \
-v /mydata/redis/node-3/data:/data \
-v /mydata/redis/node-3/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
docker run -p 6374:6379 -p 16374:16379 --name redis-4 \
-v /mydata/redis/node-4/data:/data \
-v /mydata/redis/node-4/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.14 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
docker run -p 6375:6379 -p 16375:16379 --name redis-5 \
-v /mydata/redis/node-5/data:/data \
-v /mydata/redis/node-5/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.15 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
docker run -p 6376:6379 -p 16376:16379 --name redis-6 \
-v /mydata/redis/node-6/data:/data \
-v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
- 创建集群
docker exec -it redis-1 /bin/sh # 进入容器
# 创建集群
redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1
- 连接集群
redis-cli -c
# 查看节点信息
cluster nodes
- 集群搭建完毕可以进行操作