docker

docker 运行环境标准化、可复制化、可迁移化

容器 : 共享宿主机内核 轻量 容器间隔离

Docker 核心概念:

  1. Image:镜像,应用模板
  2. Container:容器,镜像运行后的实例
  3. Registry:仓库,存放镜像
  4. Engine:引擎,负责管理镜像、容器、网络、存储
  5. Volume:数据卷,负责持久化
  6. Network:网络,负责容器通信

1.安装

使用的环境为rocky linux 9.5

docker文档官网 : https://docs.docker.com/

1.1 使用yum在线进行安装

// 添加gcc编译环境
yum -y install gcc
yum -y install gcc-c++
// 添加yum版本控制工具
yum -y install  yum-utils

// 添加阿里云镜像源
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 

// 安装docker
yum -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

// 启动docker
systemctl start docker
// 开机自启
systemctl enable docker 
systemctl is-enabled docker

1.2 卸载

systemctl stop docker
yum remove docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
rm -rf /var/lib/docker
rm -rf /var/lib/containerd

1.2 使用压缩包进行安装

下载安装包地址:https://download.docker.com/linux/static/stable/
# tgz 是 tar.gz
tar xzvf FILE.tgz

cp docker/* /usr/bin/

docker version

# 创建docker的systemd服务文件

touch /etc/systemd/system/docker.service

cat > /etc/systemd/system/docker.service <<'EOF'
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service containerd.service
Wants=network-online.target

[Service]
Type=notify
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s

[Install]
WantedBy=multi-user.target
EOF

mkdir -p /var/lib/docker
mkdir -p /etc/docker

systemctl daemon-reload

// 启动docker
systemctl start docker
// 开机自启
systemctl enable docker 
systemctl is-enabled docker

2.配置加速器

蠢的连docker都墙,每次还得从阿里云上边往下爬蛋疼吗?
# /etc/docker/daemon.json

cat > /etc/docker/daemon.json << 'EOF'
{
"registry-mirrors": 
    ["https://docker.m.daocloud.io",
    "https://huecker.io",
    "https://dockerhub.timeweb.cloud",
    "https://noohub.ru"]
}
EOF


systemctl daemon-reload
systemctl restart docker


# 使用国内轩辕hub库
echo $password | docker login -u $id --password-stdin docker.xuanyuan.run

docker pull docker.xuanyuan.run/library/xxx:xxx1.1

3. docker命令

3.1 帮助启动类命令

  • systemctl start docker
  • systemctl stop docker
  • systemctl restart docker
  • systemctl status docker
  • systemctl enable docker
  • systemctl disable docker
  • docker info
  • systemctl daemom-reload

3.2 镜像命令

  • docker images
  • docker search --limit 5 redis
  • docker pull xxx[:v1]
  • docker system df
  • docker rmi $id

3.3 容器命令

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
  • docker run

    • --name
    • -d 后台运行
    • -i (interactive)
    • -t (tty)
    • -P 随机端口映射
    • -p 指定端口映射
  • docker rm (-f)

    • docker ps -qa | xargs docker rm 删除所有容器
  • docker ps
  • docker restart
  • docker stop
  • docker kill
  • docker logs
  • docker top
  • docker inspect
  • docker port
  • docker rename 源容器名称 新容器名称
  • docker exec -it ID /bin/bash docker attach 直接进入容器启动的终端 exit会使容器停止
  • docker cp ID:容器内路径 目的主机地址
  • docker export ID > xxx.tar 将容器备份
  • docker import xxx.tar name:V1.1 恢复备份
  • docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录 镜像名

4.镜像

  • docker commit -m="提交的信息" -a="作者" 容器ID 要创建的目标镜像名:V1.1
  • docker tag 容器ID(源镜像名) regionID/name/xxx:V1.1(新镜像名)
  • docker pull
  • docker push
  • docker inspect
  • docker save -o 文件名.tar 镜像名:标签

5.仓库

5.1阿里云仓库

参考阿里云容器镜像服务

aliyun.com

5.2本地仓库

`Docker挂载主机目录访问如果出现cannot open directory .: Permission denied
解决办法:在挂载目录后多加一个--privileged=true参数即可
如果是CentOS7安全模块会比之前系统版本加强,不安全的会先禁止,所以目录挂载的情况被默认为不安全的行为,在SELinux里面挂载目录被禁止掉了额,如果要开启,我们一般使用--privileged=true命令,扩大容器的权限解决挂载目录没有权限的问题,也即使用该参数,container内的root拥有真正的root权限,否则,container内的root只是外部的一个普通用户权限。`


docker pull registry 

docker run --name=registry -d -p 5000:5000 -v /huan/myRegistry/:/tmp/registry --privileged=true 镜像ID

curl -XGET http://127.0.0.1:5000/v2/_catalog

docker tag rocky01:v2 127.0.0.1:5000/huanhuan:v1.1

# /etc/docker/daemon.json 中添加
"insecure-registries":["127.0.0.1:5000"]

docker push 127.0.0.1:5000/huanhuan:v1.1

curl -XGET http://127.0.0.1:5000/v2/_catalog

docker pull 127.0.0.1:5000/huanhuan:v1.1

6.容器数据卷

6.1 容器挂载数据卷

#使用rocky镜像创建容器测试    
docker run --name=rocky01 -d -it -v /huan/docker/rocky01Mount/:/huan/test:rw --privileged=true rocky:latest /bin/bash

docker inspect 容器ID  查看mount 可以查看到容器挂载的详细信息

# 在容器中创建文件进行测试, /huan/test/下的文件会持久化到宿主机目录中

# :rw 默认是读写权限,可不写  :ro 为只读

6.2 继承数据卷

docker run -it --privileged=true --volumes-from 父类 --name xx 镜像ID

7.进阶

7.1 mysql主从复制

## 创建master
docker run -p 3306:3306 --name mysql-master \
-v /mydata/mysql-master/log/:/var/log/mysql \
-v /mydata/mysql-master/data:/var/lib/mysql \
-v/mydata/mysql-master/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=root -d docker.xuanyuan.run/mysql/mysql-server:5.7

## 配置conf /mydata/mysql-master/conf/my.cnf
[mysqld]
## 设置server_id,同一局域网中需要唯一
server_id=101 
## 指定不需要同步的数据库名称
binlog-ignore-db=mysql  
## 开启二进制日志功能
log-bin=mall-mysql-bin  
## 设置二进制日志使用内存大小(事务)
binlog_cache_size=1M  
## 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed
## 二进制日志过期清理时间。默认值为0,表示不自动清理
expire_logs_days=7
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062


## 在主数据库中创建数据同步用户
CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';
show master status;


## 创建slave
docker run -p 3307:3307 --name mysql-slave \
-v /mydata/mysql-slave/log/:/var/log/mysql \
-v /mydata/mysql-slave/data:/var/lib/mysql \
-v/mydata/mysql-slave/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=root -d docker.xuanyuan.run/mysql/mysql-server:5.7

## 配置conf /mydata/mysql-slave/conf/my.cnf
## 设置server_id,同一局域网中需要唯一
[mysqld]
server_id=102
## 指定不需要同步的数据库名称
binlog-ignore-db=mysql  
## 开启二进制日志功能
log-bin=mall-mysql-slave1-bin
## 设置二进制日志使用内存大小(事务)
binlog_cache_size=1M  
## 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed
## 二进制日志过期清理时间。默认值为0,表示不自动清理
expire_logs_days=7
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062
## relay_log配置中继日志
relay_log=mall-mysql-relay-bin
## log_slave_updates 表示slave将复制事件写进自己的二进制日志
log_slave_updates=1
## slave设置为只读(具有super权限的用户除外)
read_only=1


## 在从数据库中配置
change master to master_host='192.168.233.186',master_user='slave',master_password='123456',master_port=3306,master_log_file='mall-mysql-bin.000001',master_log_pos=617,master_connect_retry=30;

show slave status \G ;

## 在主数据中开启主从同步
start slave;


## 测试同步
create database db01;
use db01;
create table t1(id int,name varchar(20));
select * from t1;

7.2 配置redis集群

7.2.1 基础配置

## 创建六个redis容器 
for i in {1..6};do docker run -d --name redis-node-$i --net host --privileged=true -v /mydata/redis/share/redis-node-$i:/data redis:latest --cluster-enabled yes --appendonly yes --port 638$i;done

## 随便进入一个redis容器  ip自行替换   创建哈希槽
redis-cli --cluster create 192.168.233.186:6381 192.168.233.186:6382 192.168.233.186:6383 192.168.233.186:6384 192.168.233.186:6385 192.168.233.186:6386 --cluster-replicas 1

redis-cli -p 6381
cluster info
cluster nodes


# -c 使用集群模式进行简单的测试
redis-cli -p 6381 -c 
FLUSHALL
set k1 v1
set k2 v2
get k1 
get k2

## 检查集群详细信息
redis-cli --cluster check 192.168.233.186:6381

## 模拟宕机  stop docker查看 clsuter nodes 状态变更情况
自己玩......

7.2.2 模拟扩容

# 创建一个主备的docker redis容器
for i in {7,8};do docker run -d --name redis-node-$i --net host --privileged=true -v /mydata/redis/share/redis-node-$i:/data redis:latest --cluster-enabled yes --appendonly yes --port 638$i;done

#添加主节点
redis-cli --cluster add-node 192.168.233.186:6387 192.168.233.186:6381

#添加从节点
redis-cli --cluster add-node --cluster-slave --cluster-master-id <主节点ID> <新从节点IP:端口> <集群中任一节点IP:端口>


#添加主节点需要重新分派哈希槽号
redis-cli --cluster reshard id:port
# 按提示输入:
#   slots to move: 例如 1000
#   destination node ID: 新节点ID
#   source node IDs: all(或指定源节点)
#   yes 确认

7.2.3 模拟缩容

redis-cli --cluster reshard 
#  要删除姐节点有多少槽位  例如 4095
#  all  自动分给其他3个节点
#  要删除主节点的ID
#  done 
#  yes

# 先删除主节点再删除从节点
redis-cli --cluster del-node <集群中任一节点IP:端口> <要删除的从节点ID>

8.Dockerfile

8.1关键字

  • FROM | 基础镜像,当前新镜像是基于哪个镜像的
  • MAINTAINER | 镜像维护者的姓名和邮箱地址
  • RUN | 容器构建时需要运行的命令,RUN是在 docker build时运行。
  • EXPOSE | 当前容器对外暴露出的端口
  • WORKDIR | 指定在创建容器后,终端默认登陆的进来工作目录,一个落脚点
  • USER | 指定该镜像以什么样的用户去执行,如果都不指定,默认是root
  • ENV | 用来在构建镜像过程中设置环境变量
  • ADD | 将宿主机目录下的文件拷贝进镜像且会自动处理URL和解压tar压缩包
  • COPY | 拷贝文件和目录到镜像中 COPY src dest
  • VOLUME | 容器数据卷,用于数据保存和持久化工作
  • CMD | Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换 ,CMD是在docker run 时运行。
  • ENTRYPOINT | 类似于 CMD 指令,但是ENTRYPOINT不会被docker run后面的命令覆盖, 而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序
命令格式:
ENTRYPOINT可以和CMD一起用,一般是变参才会使用 CMD ,这里的 CMD 等于是在给 ENTRYPOINT 传参。
当指定了ENTRYPOINT后,CMD的含义就发生了变化,不再是直接运行其命令而是将CMD的内容作为参数传递给ENTRYPOINT指令,他两个组合会变成

案例如下:假设已通过 Dockerfile 构建了 nginx:test 镜像:
 按照dockerfile编写执行               传参运行
 docker run nginx:test                 docker run nginx:test -c /etc/nginx/new.conf
 nginx -c /etc/nginx/nginx.conf     nginx -c /etc/nginx/new.conf

8.2 示例

centos 镜像需要带vim,jdk,ifconfig

FROM centos
LABEL maintainer="huan"
ENV MYPATH /usr/local
WORKDIR $MYPATH

# 备份镜像
RUN mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
# 使用阿里云镜像 
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
# 生成缓存
RUN yum makecache
# 安装vim编辑器
RUN yum -y install vim
# 安装 ifconfig 命令查看网络IP
RUN yum -y install net-tools
# 安装java8及lib库
RUN yum -y install glibc.i686
# 清理yum 缓存
RUN yum clean all
RUN mkdir /usr/local/java
# ADD 是相对路径 jar, 把jdk-8u 添加到容器中,安装包必须要和Dockerfile 文件在同一位置
ADD jdk-8u491-linux-i586.tar.gz /usr/local/java/
# 配置java环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_491
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
ENV PATH $JAVA_HOME/bin:$PATH
 
EXPOSE 80

CMD echo $MYPATH
CMD echo "success----------ok"
CMD /bin/bash 

8.3 构建

docker build -t 新镜像名字:TAG .

8.4 虚悬镜像

# 显示所有的虚悬镜像
docker images ls -f dangling=true
# 删除
docker images prune

9.docker网络

9.1 常用的基本命令

# 查看网络
docker network ls
# 查看网络源数据
docker network inspect xxx
# 创建
docker network create xx
docker network rm xx

容器之间的互联和通信以及端口映射

容器IP变动时候可以通过服务名直接网络通信而不受到影响

9.2 网络模式

网络模式含义适用场景
bridge为每一个容器分配、设置IP等,并将容器连接到一个docker0 虚拟网桥,默认为该模式通用场景、微服务
host容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口高性能、监控工具
none容器有独立的Network namespace,但并没有对其进行任何网络设置,如分配veth pair 和网桥连接,IP等安全沙箱、离线计算
container新创建的容器不会创建自己的网卡和配置自己的IP,而是和一个指定的容器共享IP、端口范围等。Sidecar、多进程应用

#  container网络模式
docker run -d -p xx:xx --network contaniner:要继承的容器 --name tomcat ....
查看容器的网卡和宿主机对应的网卡
#查看容器的网卡序号与宿主机对应
cat /sys/class/net/eth0/iflink
# 输出  63

#宿主机上ip a
63: veth2a6a760@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue         master docker0 state UP group default 
    link/ether a6:2a:0e:31:30:de brd ff:ff:ff:ff:ff:ff link-netnsid 4
    inet6 fe80::a42a:eff:fe31:30de/64 scope link 
    valid_lft forever preferred_lft forever

9.3 使用自定义网络

docker --network create xx
docker run -d --network xx --name alpine1 alpine:v1 
docker run -d --network xx --name alpine2 alpine:v1
# 在容器内部ping容器名称
ping alpine1 

10.容器编排

10.1 常用命令

# 查看帮助
docker compose -h

# 启动所有服务
docker compose up

# 后台启动所有服务
docker compose up -d

# 停止所有服务
docker compose down

# 查看服务状态
docker compose ps

# 查看编排过的容器进程
docker compose top

# 查看日志
docker compose logs

# 动态查看日志
docker compose logs -f

# 检查配置
docker compose config

# 检查配置,有问题才有输出
docker compose config -q

# 重启所有服务
docker compose restart

# 重启指定服务
docker compose restart web

# 进入容器
docker compose exec web bash

# 构建镜像
docker compose build

# 拉取镜像
docker compose pull

# 删除停止的容器
docker compose down

# 删除容器和卷
docker compose down -v

10.2 标准模板

services:
  app:
    image: 镜像名:版本
    container_name: 容器名
    # 如果需要映射端口,格式是:宿主机端口:容器端口
    ports:
      - "8080:80"
    # 环境变量,简单变量可以直接写这里
    environment:
      - TZ=Asia/Shanghai
    # 也可以把密码、数据库名等放到 .env 文件
    env_file:
      - .env
    # 宿主机目录挂载到容器内部
    volumes:
      - ./data:/app/data
      - ./logs:/app/logs
      - ./conf:/app/conf:ro
    # 容器异常退出或服务器重启后自动恢复
    restart: unless-stopped
    # 加入自定义网络
    networks:
      - app-net
    # 日志限制,防止 Docker 日志撑爆磁盘
    logging:
      driver: json-file
      options:
        max-size: "100m"
        max-file: "3"
networks:
  app-net:
    driver: bridge