Docker 安装与使用
Docker 安装
# 安装必要软件包
yum install -y yum-utils device-mapper-persistent-data lvm2
# 设置Docker镜像源
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
sed -i 's+download.docker.com+mirrors.aliyun.com/docker-ce+' /etc/yum.repos.d/docker-ce.repo
yum makecache fast
# 安装 docker-ce 版本
yum install docker-ce -y
# 启动Docker服务
systemctl start docker
# 设置Docker随系统启动
systemctl enable docker
Docker 服务命令
# 查看 Docker 版本
docker --version
docker -v
# 启动Docker服务
systemctl start docker
# 停止Docker服务
systemctl stop docker
# 重启Docker服务
systemctl restart docker
# 查看Docker服务状态
systemctl status docker
# 设置Docker随系统启动
systemctl enable docker
Docker 镜像命令
# 列出所有本地镜像,-a 包括中间镜像
docker images
# 搜索镜像
docker search 镜像名称
# 拉取镜像
docker pull 镜像名称:版本号
# 删除镜像,删除需要先删除相关容器,-f 可以强制删除,容器ID可以只输入前几位
docker rmi 镜像ID或镜像名:版本号
# 加载自定义镜像(加载自己的镜像文件.tar)
docker load -i 镜像文件名称.tar
Docker 容器命令
# 创建并启动一个新的容器(创建时需要设置很多配置,如端口号,挂载目录等等)
# OPTIONS:
# -d 后台运行
# -p 端口映射
# -v 本地目录:容器内目录 (挂载目录)
# -e 设置参数
# --name 名称 容器命名
# --restart=always 随docker服务启动
# --network my01 指定容器所属的网络,没有my01网络会自动创建
docker run [OPTIONS] 镜像名[:TAG] [COMMAND] [ARG...]
# 容器挂载需要注意事项
# 挂载目录只能在创建容器的时候使用 -v 进行挂载
# 挂载目录语句格式为:-v 本地目录:容器内目录
# 以/或./开头是使用本地目录挂载,如: -v /data:/var/lib/data
# 如果直接以名称开头则会被识别为数据卷而非本地目录 如:-v data:/var/lib/data
# 数据卷默认存储位置为宿主机的/var/lib/docker/volumes下,docker run 创建时,没有数据卷会自动创建
# 有一部分容器在创建时,如果没有进行挂载,会自动创建数据卷对容器的关键数据目录进行挂载,如mysql
# 查看容器挂载目录可以使用docker inspect 容器ID或容器名 ,查询容器详细信息中的 Mounts
docker run -v 本地目录:容器内目录 mysql
# 列出当前运行的容器,-a 列出所有容器
docker ps
# 查看容器详情信息
docker inspect 容器ID或容器名
# 启动已存在的容器
docker start 容器ID或容器名
# 停止运行中的容器
docker stop 容器ID或容器名
# 重启容器
docker restart 容器ID或容器名
# 拷贝容器中的文件出来
docker cp 容器ID或名称:目标路径 源文件或目录
# 拷贝文件到容器中去
docker cp 源文件或目录 容器ID或名称:目标路径
# 进入容器执行命令
docker exec -it 容器ID或容器名 /bin/bash
# 删除容器
docker rm 容器ID或容器名
# 设置已运行的容器随docker服务启动而自启
docker update --restart=always 容器ID或容器名
Docker Network 网络
默认网络docker0
有时会出现一种需求,就是容器之间的互相访问,所以需要了解Docker容器是如何分配网络的。
系统在安装后,会创建一个虚拟网卡叫docker0
以CentOS7.9为例,使用 ip addr命令查看网络
ens33为宿主机网络
docker0就是安装docker后自动创建的虚拟网卡
IP为 172.17.0.1/16 (16的意思为前16为不可改变,ip转二进制,一组是8位,所以是172.17不可改变)
创建容器后容器的IP会自动非配,如172.17.0.2,172.17.0.3,它们都以bridge(桥接)的方式链接到Docker的虚拟网卡上。
容器之间使用IP即可互相访问,但是使用默认网络(docker0)会有一个问题,就是每次容器重启后分配的IP可能会不一样。
比如MySQL容器的IP是172.17.0.2,下载重启后,.0.2被Redis容器占用,那么MySQL就会分配到172.17.0.3,这样就会导致容器与容器之间连接失败。
自定义网络
加入自定义网络的容器可以通过容器名互相访问,这样就解决了自动分配IP发生变化的问题。
在创建容器时,可以使用 --network 网络名,来指定容器所属的自定义网络,网络名不存在时会自动创建。
之后就需要使用docker netwrok命令来对容器的网络进行操作了。
# 创建一个新的自定义网络
docker network create 网络名
# 列出所有的网络
docker network ls
# 显示一个或多个网络的详细信息
docker network inspect 网络名
# 删除一个或多个网络
docker network rm 网络名
# 将一个或多个容器连接到网络
docker network connect 网络名 容器名或容器ID
# 将一个或多个容器从网络中断开连接
docker network disconnect 网络名 容器名或容器ID
# 删除所有未使用的网络
docker network prune
镜像结构
镜像分层
在拉取镜像时,会发现有这么一段信息
这代表着一个镜像结构有多个分层镜像组成。
这些分层镜像分为三类
入口( Entrypoint )
镜像运行的入口,一般是程序启动的脚本和参数。
层 ( Layer )
添加安装包、依赖、配置等,如拷贝jar包,安装jar包,配置环境变量等等。
每次操作都会形成新的一层。
基础镜像 ( BaseImage )
应用依赖的系统函数库、环境、配置、文件等。
为什么要分层?
这种设计方式,加快了用户的下载速度。
用户拉取镜像后,镜像的分层镜像都存储在本地系统上,当用户拉取新镜像时,如果使用到本地系统中的分层镜像,这一层即可不用下载直接拉取完成。
以 java 项目举例
镜像由 ubuntu:16.04 为基础镜像
拷贝 jar 包为层镜像
安装 JDK8 和配置环境变量为层镜像
运行 jar 包命令为入口镜像
当要部署其他项目时,因为本地系统中已经存在之前部署的镜像,除了拷贝 jar 包这一层镜像需要重新生成,其他的都会立即完成。
Dockerfile
Dockerfile 是用于自动化构建 Docker 镜像的文本文件,它包含了一系列用于定制镜像的指令。
常见指令
指令的使用
以下使用 ubuntu:16.04为基础镜像,安装jdk,拷贝jar,运行java项目
# 基础镜像
FROM ubuntu:16.04
# 配置环境变量
ENV JAVA_DIR=/usr/local
# 拷贝jdk和java项目的包
COPY ./jdk8.tar.gz $JAVA_DIR/
COPY ./java-demo.jar /java-demo.jar
# 安装JDK
RUN cd $JAVA_DIR \ && tar -xf ./jdk8.tar.gz \
&& mv ./jdk1.8.0_144 ./java8
# 配置环境变量
ENV JAVA_HOME=$JAVA_DIR/java8
ENV PATH=$PATH:$JAVA_HOME/bin
#入口.java项目的启动命令
ENTRYPOINT ["java", "-jar", "java-demo.jar"]
上面是为了演示指令的使用,实际运行java项目可以使用jdk8为基础镜像来运行
# 基础镜像
FROM openjdk:8-jre
# 拷贝jar包
COPY ./java-demo.jar /java-demo.jar
#入口.java项目的启动命令
ENTRYPOINT ["java", "-jar", "java-demo.jar"]
运行Dockerfile构建镜像
# 语句格式 docker built -t 镜像名:镜像版本号 Dockerfile所在目录
# -t :给镜像起名,格式为repository:tag,不指定tag时,默认为latest
# . :是指定Dockerfile的所在目录,如果在当前目录,则指定为"."
docker build -t myImage:1.0 .
docker-compose工具
Docker Compose通过一个单独的docker-compose.yaml 模板文件(YAML格式)来定义一组相关联的应用容器,帮助我们实现多个相关联的Docker容器的快速部署。
安装
在 Linux 系统上安装
# 这里 v2.12.2 是示例版本号,请替换为实际要下载的版本。
sudo curl -L "https://github.com/docker/compose/releases/download/v2.12.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# 设置执行权限
sudo chmod +x /usr/local/bin/docker-compose
# 验证安装
docker-compose --version
模板文件
简单Docker run命令与docker-compose.yaml文件对比
# docker run 创建mysql命令
docker run -d \
--name mysql \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=123456 \
-e TZ=Asia/Shanghai \
-v /usr/local/mysql/conf:/etc/mysql/conf.d \
-v /usr/local/mysql/logs:/logs \
-v /usr/local/mysql/data:/var/lib/mysql \
--restart=always \
--network my-network \
mysql:5.7
# 打开docker-compose.yaml文件
vi docker-compose.yaml
# docker-compose.yaml内容
# 指定 Docker Compose 的版本,这里是 3.8 版本。
version: "3.8"
services:
# 这里的mysql为这个services的名称,如果不指定container_name就会是容器默认名称
mysql:
# 这里的mysql为容器名称,docker run --name mysql
container_name: mysql
# 这里为镜像名
image: musql5.7
# 开放端口,这里为了演示多个端口开放,实际mysql开放3306即可
ports:
- "3306:3306"
- "3307:3307"
# 指定参数 ,docker run -e
environment:
MYSQL_ROOT_PASSWORD=123456
TZ=Asia/Shanghai
# 目录挂载,docker run -v
volumes:
- /usr/local/mysql/conf:/etc/mysql/conf.d
- /usr/local/mysql/logs:/logs
- /usr/local/mysql/data:/var/lib/mysql
networks:
- my-networks
复杂模板
# 指定 Docker Compose 的版本,这里是 3.x 版本。
version: "3"
services:
# 容器1: halo, 镜像存在于docker hub 上
halo:
image: halohub/halo:2.15
# 当服务因错误停止时,尝试重启最多 3 次。
restart: on-failure:3
# Halo 服务依赖于 halodb 服务,并且只有当 halodb 服务健康时才启动。
depends_on:
halodb:
condition: service_healthy
# 将 Halo 服务连接到名为 halo_network 的网络。
networks:
halo_network:
# 映射本地的 ./halo2 目录到容器内的 /root/.halo2,用于持久化数据。
volumes:
- ./halo2:/root/.halo2
ports:
- "8090:8090"
# 设置健康检查,每 30 秒检查一次 Halo 应用的健康状态,初始等待 30 秒,超时时间 5 秒,失败后重试 5 次。
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8090/actuator/health/readiness"]
interval: 30s
timeout: 5s
retries: 5
start_period: 30s
# 设置启动 Halo 应用时使用的命令行参数,包括数据库连接信息等。
command:
- --spring.r2dbc.url=r2dbc:pool:mysql://halodb:3306/halo
- --spring.r2dbc.username=root
# MySQL 的密码,请保证与下方 MYSQL_ROOT_PASSWORD 的变量值一致。
- --spring.r2dbc.password=o#DwN&JSa56
- --spring.sql.init.platform=mysql
# 外部访问地址,请根据实际需要修改
- --halo.external-url=http://localhost:8090/
# 容器2:mysql, 镜像存在于docker hub 上
halodb:
image: mysql:8.1.0
restart: on-failure:3
# 类似 Halo 服务,设置重启策略和网络连接。
networks:
halo_network:
# MySQL 启动命令,设置字符集、认证插件等。
command:
- --default-authentication-plugin=caching_sha2_password
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_general_ci
- --explicit_defaults_for_timestamp=true
volumes:
- ./mysql:/var/lib/mysql
- ./mysqlBackup:/data/mysqlBackup
ports:
- "3306:3306"
# 设置 MySQL 的健康检查。
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "--silent"]
interval: 3s
retries: 5
start_period: 30s
# 设置 MySQL 的 root 密码和默认数据库名。
environment:
# 请修改此密码,并对应修改上方 Halo 服务的 SPRING_R2DBC_PASSWORD 变量值
- MYSQL_ROOT_PASSWORD=o#DwN&JSa56
- MYSQL_DATABASE=halo
# 容器3:自己的java项目,镜像需要制作
my-project:
container_name: my-project
# 构建镜像方式为dockerfile
# 注意这里的context: ./app 相对路径的起点是docker-compose.yaml的位置
# ./app目录下要有dockerfile文件,然后会使用里面的指令构建镜像
# 如果dockerfile就在当前目录使用"."即可
build:
context: ./app
dockerfile: dockerfile
ports:
- "8080:8080"
depends_on:
halodb:
condition: service_healthy
networks:
halo_network:
# 网络配置,定义一个名为 halo_network 的网络,供服务间通信使用。
networks:
halo_network:
命令
# 查看docker-compose版本信息
docker-compose version
# 以下命令要在docker-compose.yaml文件所在目录使用
# 检查 docker-compose.yml 文件的语法,并显示解析后的配置。
docker-compose config
# 构建启动所有容器
docker-compose up -d
# 构建启动某个容器
docker-compose up -d 服务名
# 停止并删除所有容器,网络,镜像等相关资源
docker-compose down
# 显示项目中所有服务的容器状态。
docker-compose ps
# 进入到容器中
docker-compose exec 服务名 /bin/bash
# 查看服务容器的日志输出。
docker-compose logs -f 服务名
# 查看容器的实时日志(从最后10行开始)
docker-compose logs --tail 10 -f 服务名
# 列出所有镜像
docker-compse images
# 构建服务的镜像(可以用于重新构建镜像)
docker-compose build 服务名
# 不带缓存的构建
docker-compose build --no-cache 服务名
# 暂停容器
docker-compose pause 服务名
# 恢复容器
docker-compose unpause 服务名
# 重启项目中的容器
docker-compose restart
# 重启项目中的某个容器
docker-compose restart 服务名
# 停止项目中的容器
docker-compose stop
# 停止项目中的某个容器
docker-compose stop 服务名
# 启动已经存在的容器。
docker-compose start
# 启动已经存在的某个容器。
docker-compose start 服务名
# 删除已经停止的容器。
docker-compose rm
# 删除已经停止的某个容器。
docker-compose rm 服务名
# 显示服务容器的进程信息。
docker-compose top