Docker
2021-10-18 本文已影响0人
陈海辉
Docker(Centos)
安装&卸载 Docker
- 安装步骤
- 官网 > Guides > Get Docker > 选择对应的平台(Mac Win Linux)
- Liunx 需展开(Installation per distro) > 选择具体的操作系统
- 注意修改源为国内源(阿里): https://download.docker.com/ > https://mirrors.aliyun.com/docker-ce/
# 卸载旧的版本
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
# 下载需要的安装包
yum install -y yum-utils
# 设置镜像的仓库(国内阿里云的)
yum-config-manager \
--add-repo \
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 更新 yum 软件包索引
yum makecache fast # Contos7
yum makecache # Contos8
# 安装docker相关的配置(docker-ce 社区版; docker-ee 企业版)
yum install docker-ce docker-ce-cli containerd.io
卸载 Docker
yum remove docker-ce docker-ce-cli containerd.io # 1. 卸载依赖
rm -rf /var/lib/docker # 2. 删除资源 /var/lib/docker是docker的默认工作路径
配置阿里镜像加速器
- 地址, 配置自己阿里云: 阿里云 > 产品 > 容器镜像服务 > 镜像工具 > 镜像加速器 > 选择操作系统
# 新建文件
sudo mkdir -p /etc/docker
# 写入配置
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://mpa24q0m.mirror.aliyuncs.com"]
}
EOF
# 守护进程重新加载
sudo systemctl daemon-reload
# 重启服务
sudo systemctl restart docker
使用 Docker
帮助命令
systemctl start docker # 启动
systemctl enable docker # 设置开机自启动
docker version # 查看当前版本号,是否启动成功
docker info # 查看 docker 的系统信息,包括镜像和容器的数量
docker 命令名 --help # 帮助命令(可查看可选的参数)
镜像命令
docker images -aq # 查看下载过的镜像: -a 列出所有镜像; -q 只显示镜像 id
docker search 镜像名 # 搜索镜像: --filter=STARS=3000 过滤收藏数大于3000的
docker pull 镜像名:版本号 # 下载镜像: 版本号在镜像仓库中查看
docker rmi 镜像名 镜像id2 # 删除镜像, 也可通过 id 来删除
docker rmi -f $(docker images -aq) # 删除所有(查询结果)
容器命令
docker run [可选参数] 镜像名 # 运行容器(本地查找 > 远程仓库查找 > 下载 > 运行)
# docker容器后台运行,必须要有一个前台的进程,否则会自动停止
docker run -d centos /bin/sh -c "while true;do echo hi;sleep 5;done" # 编写shell脚本循环执行,使得centos容器保持运行状态
#参数说明
--name="名字" # 指定容器名字 xxx1 xxx2 用来区分容器
-d # 后台方式运行
-it # 交互方式运行: docker run -it centos /bin/bash # 启动并进入容器, 并用 bash 控制台交互
-p # 指定容器的端口
-p 主机端口:容器端口 # 常用
-p ip:主机端口:容器端口 配置主机端口映射到容器端口
-p 容器端口
-P # 随机指定端口(大写的P)
-e ES_JAVA_OPTS="-Xms128m -Xmx512m" # 环境配置, 限制最大内存占用情况
--net # 使用网络连接, 多个容器间通信
docker stats # 查看资源使用情况
docker history 容器id # 查看容器的构建过程(倒序)
exit # 停止并退出容器(后台方式运行则仅退出)
Ctrl+P+Q # 不停止容器退出
docker ps # 列出所有正在运行的容器
-a # 所有(包括已停止的)
-q # 只显示容器id
-n=? # 最近几条
docker rm 容器id # 删除指定的容器 不能删除正在运行的容器,强制删除使用 rm -f
docker rm -f $(docker ps -aq) #删除所有的容器
docker ps -a -q|xargs docker rm #删除所有的容器
docker start 容器id # 启动容器
docker restart 容器id # 重启容器
docker stop 容器id # 停止当前运行的容器
docker kill 容器id # 强制停止当前容器
其他常用命令
docker logs -tf 容器id # 查看日志
docker logs --tail number 容器id # num为要显示的日志条数
docker top 容器id # 查看容器中进程信息
docker inspect 容器id # 查看容器的元数据: 启动时参数, 配置...
# 进入当前正在运行的容器(后台方式转交互方式)
docker exec -it 容器id /bin/bash # 方式一(常用): 进入容器后开启一个新的终端, 可在里面操作
docker attach 容器id # 方式二: 进入容器正在执行的终端(正在执行当前代码)
# 拷贝容器的文件到主机中
docker cp 容器id:容器内路径 目的主机路径 # 拷贝是一个手动过程, 未尝不可通过 -v 卷的技术实现
# 提交容器到本地镜像
# 例: 1. 启动一个默认的 tomcat
# 2. 发现这个默认的没有 webapps 应用(镜像的原因)
# 3. 我自己拷贝进去了基本的文件
# 4. 将修改后的容器通过 commit 提交为一个本地镜像, 以后就可以用修改后的镜像
docker commit -m=“提交的描述信息” -a="作者" 容器id 目标镜像名:[TAG]
image.png
image.png
可视化工具
- Portaniner: Docker 的图形化管理工具,类似的工具还有Rancher(CI/CD再用)
# 安装
docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
# 访问(需暴露阿里云的 8088 端口): https://ip地址:8088/
镜像
安装 Nginx
- 搜索镜像 search: 建议官网搜索
- 下载镜像 pull
- 查看是否下载完成 images
- 启动: docker run -d --name nginx01 -p 8080:80 nginx
安装 Mysql
docker pull mysql:5.7 # 下载镜像
# 启动 后台 端口映射 配置文件数据卷 数据表数据卷 配置密码
docker run -d -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=mysql的密码 mysql:5.7
其它注意事项
# 限制 最大内存使用量(有的镜像太费内存, 导致所有都卡)
# -e ES_JAVA_OPTS="-Xms128m -Xmx512m"
docker run -d --name elasticsearch01 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms128m -Xmx512m" elasticsearch:7.6.2
容器数据卷
- 数据(放哪里), 若放在容器中, 则容器删除, 数据也丢失
- 容器间有个数据共享技术,容器产生的数据,同步到本地
- 卷技术: 目录的挂载,将容器的数据目录,挂载到 Linux 下
使用数据卷(方式一)
# 指定路径挂载: -v 主机目录:容器目录
# 匿名挂载: -v 容器目录 => 卷名为一串 hash 串
# 具名挂载(常用): -v 卷名:容器目录 => 所有未指定主机目录的, 默认挂载的主机目录为 `/var/lib/docker/volumes/xxx/_data`
docker run -it -v /home/xxx:/home:读写权限 镜像名 /bin/bash
# 读写权限: ro 只读(在容器内无法修改); rw 可读写(默认可双向修改)
# 查看是否挂载成功 docker inspect 容器id > Mounts
docker volume ls # 查看所有卷信息
docker volume inspect 卷名 # 查看卷详情: Mountpoint 挂载的主机目录
Dockerfile(方式二)
- 用来构建 docker 镜像的构建文件 的命令脚本
# Dockerfile
FROM centos # 基础镜像
VOLUME ["挂载数据卷目录1", "挂载数据卷目录2"] # 匿名挂载两个目录
CMD echo "----- 执行结束 -----" # 执行终端命令
CMD /bin/bash
# 根据 Dockerfile 来生成镜像: -f 命令脚本路径; -t(target) 生成的镜像名; . 当前目录
docker build -f /Dockerfile所在路径 -t 镜像名:TAG号 .
数据卷容器
- 多个 mysql 同步数据
docker run -it --name 父容器名 镜像名 # 启动一个父容器(数据卷容器)
docker run -it --name 子容器名 --volumes-from 父容器名 镜像名 # 启动一个子容器, 数据卷来源于父容器
# 例: 多个 mysql 共享数据
docker run -d -p 3306:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=mysql密码 --name mysql01 mysql:5.7 # 运行第一个容器(数据卷容器)
docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=mysql密码 --name mysql02 --volumes-from mysql01 mysql:5.7 # 运行第二个容器, 继承第一个容器的数据卷
Dockerfile
-
Dockerfile 是用来构建 docker 镜像的文件!命令参数脚本!
-
基础知识
- 每个保留关键字(指令)都须是大写字母
- 执行从上到下顺序执行
-
#
表示注释 - 每个指令都会创建提交一个镜像层, 并提交
-
构建步骤
- 编写一个 Dockerfile 文件
- docker build 构建成一个本地镜像
- docker run 运行镜像
- docker push 发布镜像(DockerHub, 阿里云镜像仓库)
-
很多官方镜像都是基础包, 很多功能没有, 我们通常会自己搭建自己的镜像
-
Dockerfile 是面向开发的,我们以后要发布项目, 做镜像, 就需编写Dockerfile文件
- Dockerfile: 构建文件, 定义了一切的步骤, 源代码
- DockerImages: 通过 Dockerfile 构建生成的镜像, 最终发布和运行的产品
- Docker 容器: 就是镜像运行起来提供的服务器
Dockerfile 的指令
FROM # 基础镜像, 一切从这里开始构建
MAINTAINER # 镜像是谁写的,姓名+邮箱
RUN # 镜像构建的时候需要运行的命令
ADD # 添加内容, 如 tomcat 镜像, 添加 tomcat 压缩包
COPY # 功能类似ADD,但是是不会自动解压文件,也不能访问网络资源
WORKDIR # 镜像的工作目录
VOLUME # 挂载的目录(容器卷)
EXPOSE # 保留端口配置
CMD # 指定这个容器启动的时候要运行的命令(只有最后一个会生效)
EMTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD # 当构建一个被继承Dockerfile,这个时候就会运行ONBUILD的指令,触发指令
ENV # 构建的时候设置环境变量
指令
CMD & EMTRYPOINT 区别
# 编写 Dockerfile 文件
FROM centos
CMD ["ls", "-a"]
EMTRYPOINT ["ls", "-a"]
# 构建镜像
docker build -f Dockerfile文件路径 -t 镜像名[:版本号] . # 这里有个小点
# run 运行
docker run 镜像id -l # 想追加一个命令: ls -al
# CMD 命令: -l 会替换 "ls -a" ==> 控制台抛错
# EMTRYPOINT 命令: -l 会追加在后面 "ls -a -l" ==> 正常使用
实战测试
- Docker Hub 中 99% 的镜像, 都是同
FROM scratch
+ 额外的软件和配置来进行的
# 1. 编写 Dockerfile 的文件
FROM centos
MAINTAINER chenhaihui<1390568920@qq.com> # 作者+联系方式
ENV MYPATH /usr/local # 环境变量
WORKDIR $MYPATH # 镜像的工作目录: 使用了变量, 值为 /usr/local
RUN yum -y install vim # 镜像构建的时候需要运行的命令 vim
RUN yum -y install net-tools # 镜像构建的时候需要运行的命令 ifconfig
EXPOSE 80 # 指定对外的窗口
CMD echo $MYPATH # 容器启动时运行的命令: 打印环境变量
CMD echo "---end---"
CMD /bin/bash # 容器启动时运行的命令: 进行到 bash 命令
# 2. 通过这个文件构建镜像
docker build -f Dockerfile文件路径 -t 镜像名[:版本号] . # 这里有个小点
Successfully built 镜像id
Successfully tagged 镜像名:版本号
# 3. 测试运行
docker images
docker run -it 镜像名:版本号
docker history 容器id # 查看容器的构建过程(倒序)
实战 Tomcat 镜像
- 准备镜像文件 tomcat 压缩包, jdk的压缩包, 新建一个 readme.txt 文件
- 编写 Dockerfile 文件: 官方命名 Dockerfile
FROM centos
MAINTAINER chenhaihui<1390568920@qq.com> # 作者+联系方式
COPY readme.txt /usr/local/readme.txt # 将本地文件拷贝到 /usr/local 目录下
ADD jdk-8u251-linux-x64.tar.gz /usr/local/ # 将本地文件添加到 /usr/local 目录下(并解压)
ADD apache-tomcat-8.5.55.tar.gz /usr/local/ # 将本地文件添加到 /usr/local 目录下(并解压)
RUN yum -y install vim # 安装 vim
ENV MYPATH /usr/local
WORKDIR $MYPATH # 工件目录
# 一大堆的环境变量
ENV JAVA_HOME /usr/local/jdk1.8.0_251
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.55
ENV CATALINA_BASH /usr/local/apache-tomcat-8.5.55
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080 # 暴露端口
CMD /usr/local/apache-tomcat-8.5.55/bin/startup.sh && tail -F /usr/local/apache-tomcat-8.5.55/bin/logs/catalina.out
- 构建镜像
docker build -t 镜像名[:版本号] .
docker images
- 运行
docker run -d -p 9090:8080 -name 容器名
-v /home/tomcat/test:/usr/local/apache-tomcat-9.0.22/webapps/test
-v /home/tomcat/logs:/usr/local/apache-tomcat-9.0.22/logs
镜像名
发布镜像到 dockerhub
-
在 dockerhub 上注册自己的账号
-
登录账号:
docker login -u 用户名
> 输入密码 -
提交自己的镜像:
docker push 镜像名
(镜像名最好使用用户名/镜像名:版本号
命名方式) -
push 镜像的问题: 增加一个 tag
docker tag 本地镜像id 用户名/镜像名:版本号 # 添加 tag
docker push 用户名/镜像名:版本号 # 提交镜像
发布镜像到 阿里云
- 登录阿里云
- 找到容器镜像服务
- 创建命名空间:防止冲突
- 创建容器镜像
- 浏览阿里云: 按步骤执行
Docker 网络
原理
- 只要安装了 docker, 就会有一个网卡 docker0 桥接模式(255.255.0.1/16),使用的技术是 evth-pair 技术
- evth-pair 技术: 就是一对虚拟设备接口,他们都是成对出现的,一段连着协议,一段彼此相连
- 因为此特性,evth-pair 充当一个桥梁,连接各种虚拟网络设备的
- OpenStac, Docker 容器之间的连接,OVS 的连接,都是使用 evth-pair 技术
- 我们每启动一个 docker 容器,docker 就会给 容器分配一个ip
- Docker 使用的是 Linux 的桥接,宿主机中是一个 Docker 容器的网桥 docker0,最多65535-2个
--link 模式(已不建议使用)
ip addr # centos ip地址: 本机回环地址; 阿里云内网地址; docker0地址
# 测试一下
docker run -d -P --name 容器名1 镜像名 # 启动一个 tomcat 容器
docker exec -it 容器名1 ip addr # 获取 tomcat 容器的 ip 地址(docker 分配的)
docker run -d -P --name 容器名2 --link 容器名1 镜像名 # 让容器名2 通过 容器名1 连接网络
docker exec -it 容器名2 ping 容器名1 # 可以直接 ping 通, 但不能反向 ping 通过
自定义网络
网络模式
- bridge: 桥接 docker(默认, 自己创建的也使用 bridge 模式)
- none: 不配置网络
- Host: 和宿主机共享网络
- Container: 容器网络连接(用的少, 局限很大)
docker network ls # 查看所有的 docker 网络
docker network inspect 网络名 # 查看网络名详情
docker run -d -P --name 容器名 镜像名 # 默认是 --net bridge, 这个就是 docker0 网络
docker0特点: 默认的, 域名不能访问, --link 可以打通连接(但很麻烦)
# 自定义一个网络: -d(driver) 网络模式; --subnet 子网掩码; --gateway 网关
docker network create -d bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 自定义网络名
# 运行容器时指定 自定义网络名: 自此, 要宿主机可通过 ip 或 容器名 ping 通网络
docker run -d -P --name 容器名 --net 自定义网络名 镜像名
网络连通
# 连通网络, 将 "容器" 放到了 "自定义网络名" 网络下
# 一个容器, 两个 ip 地址(阿里云 公网ip 私网ip)
docker network connect 自定义网络名 容器名
实战: 部署 Redis 集群
# 1. 创建一个 redis 的自定义网络名
docker network create redis --subnet 172.38.0.0/16
# 2. 通过 shell 脚本创建 6 个 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
docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port} \
-v/mydata/redis/node-${port}/data:/data \
-v/mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.1${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf; # 循环创建容器, 也可一个个的启动
# 3. 创建集群: 是否按此配置 ==> 输入 yes
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
# 4. 操作集群
docker exec -it redis-1 /bin/sh # 进入一个容器
redis-cli -c # redis 客户端连接集群
cluster info # 集群信息
cluster nodes # 查看集群
set a 124 # 存储值
get a # 获取值