第四周作业

Dockerfile命令.

Dockerfile命令

FROM

!!! note 基本信息

  • 用途
    • 所有的镜像都通过基础镜像而来,该语句指定基础镜像是谁,基于什么镜像来做。
  • 格式
    • FROM [--platform=<platform>] <image> [AS <name>]

    • FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]

    • FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]

    • --platform 指定镜像的平台,比如: linux/amd64, linux/arm64, or windows/amd64

    • tagdigest是可选项,如果不指定,默认为latest
      !!!

!!! tip 常见用法

  1. 完全自建镜像,需要空镜像
    FROM scratch

    scratch是一切镜像的起源,它本身无具体的操作系统,可以理解为一个占位符
    它本质上是一个 0 字节的镜像
    对于静态编译中,多阶段编译有奇效

    # 使用 golang 基础镜像进行构建
    FROM golang:1.16 AS builder
    
    # 设置工作目录
    WORKDIR /app
    
    # 复制 Go 项目文件到容器中
    COPY . .
    
    # 静态编译 Go 程序
    RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o myapp .
    
    # 使用 scratch 空白镜像作为最终镜像
    FROM scratch
    
    # 从构建阶段复制编译好的可执行文件到最终镜像
    COPY --from=builder /app/myapp /
    
    # 定义容器启动时执行的命令
    CMD ["/myapp"]
  2. 从精简操作系统的基础下构建
    FROM busybox / FROM alpine

    精简操作系统一般在 10M之内,这些系统具备最基础的功能能够胜任一般的错误排查
    不至于如空白镜像,需要自行对工具进行选型、依赖解决等、可以较好地完成部署任务
    是一个性价比极高的基础镜像

  3. 从完整操作系统镜像下构建
    FROM ubuntu / FROM Rockylinux

    这些一般为主流操作系统,用户最为熟悉,拥有的系统工具丰富,对于故障和配置排查提供了基础
    一般具备主流的bash,而不是精简系统的sh
    大小一般在100M500M之间

  4. 从应用镜像构建
    FROM redis / FROM jenkins

    这类镜像已经是完整的应用,其空间大小与应用和其选择的系统基座相关
    从这一类镜像进行构建,一般是为了实现告警的自定义功能或精简配置
    !!!

!!! warning 注意事项

  • 应尽量选择体积小的镜像构建,有助于提升性能和资源的使用比
    !!!

LABEL

!!! note 基本信息

  • 用途
    • 指定元数据,用于标识系统地址、用户、帐号、维护者等公开信息
  • 格式
    • LABEL <key>=<value> <key>=<value> <key>=<value> ...
      !!!

!!! tip 常见用法

  • 维护者信息
    LABEL maintainer="alfiecheung <root@alfiecheung.com>"

!!!

!!! warning 注意事项

!!!

RUN

!!! note 基本信息

  • 用途
    • 用来在构建镜像阶段需要执行 FROM 指定镜像所支持的Shell命令
  • 格式
    #shell 格式: 相当于 /bin/sh -c
    <命令>
    此种形式支持环境变量
    RUN <命令>
    #exec 格式: 此种形式不支持环境变量,注意:是双引号,不能是单引号
    RUN ["executable","param1","param2"...]
    #exec格式可以指定其它shell
    RUN ["/bin/bash","-c","echo hello wang"]

!!!

!!! tip 常见用法

# 多个命令通过 && 操作符联合,为的是减少构建时的层数
RUN yum -y install epel-release \
    && yum -y install nginx \
    && rm -rf /usr/share/nginx/html/*
    && echo "<h1> docker test nginx </h1>" > /usr/share/nginx/html/index.html

!!!

!!! warning 注意事项

  • shell格式命令,默认使用/bin/sh去解析,具有较多的限制性

  • exec格式命令,可通过修改第一个变量为所需的shell进行命令那个解析

  • 命令执行没有上下文,如下执行是错误的

#world.txt并不存放在/app内
RUN cd /app
RUN echo "hello" > world.txt

# 应修改为
RUN echo "hello" > /app/world.txt

!!!

ENV

!!! note 基本信息

  • 用途
    • 环境变量的设置
  • 格式
    #变量赋值格式1
    #此格式只能对一个key赋值,<key>之后的所有内容均会被视作其<value>的组成部分
    ENV <key> <value>
    
    #变量赋值格式2
    #此格式可以支持多个key赋值,定义多个变量建议使用,减少镜像层
    ENV <key1>=<value1> <key2>=<value2>

!!!

!!! tip 常见用法

  1. 配置应用程序参数

    ENV DATABASE_HOST=localhost
    ENV DATABASE_PORT=5432
    ENV API_KEY=abc123
  2. 指定工作目录

    ENV APP_HOME=/app
    WORKDIR $APP_HOME
  3. 设置语言环境

    ENV LANG=en_US.UTF-8
    ENV LC_ALL=en_US.UTF-8
  4. 传递构建参数

    ARG VERSION
    ENV APP_VERSION=$VERSION

!!!

!!! warning 注意事项

  • ENV 可以定义环境变量和值
  • 能被后续指令(如:ENV,ADD,COPY,RUN等)通过$KEY或${KEY}进行引用,并在容器运行时保持
    FROM  rockylinux:9.3 
    LABEL maintainer="alfiecheung <root@alfiecheung.com>"
    ENV name="leslie" age=20
    RUN echo "${name}:${age}" > /tmp/test.txt
    
    # 通过运行容器,查看 /tmp/test.txt
    # docker run --rm rocky:env-test2 cat /tmp/test.txt
    # leslie:20

!!!

COPY

!!! note 基本信息

  • 用途
    • 本地宿主机与容器之间文件的互相复制
  • 格式
    COPY [--chown=<user>:<group>] <src>... <dest>
    COPY [--chown=<user>:<group>] ["<src>",... "<dest>"] #路径中有空白字符时,建议使用此格式

!!!

!!! tip 常见用法

  1. 复制单个文件:

    COPY source.txt /app/destination.txt

    将主机上的 source.txt 文件复制到容器中的 /app/destination.txt

  2. 复制整个目录:

    COPY source_directory /app/destination_directory

    将主机上的 source_directory 目录及其所有内容递归地复制到容器中的 /app/destination_directory

  3. 复制多个文件:

    COPY file1.txt file2.txt /app/

    将主机上的 file1.txtfile2.txt 文件复制到容器中的 /app/ 目录。

  4. 使用通配符复制多个文件:

    COPY *.txt /app/

    将主机上所有以 .txt 结尾的文件复制到容器中的 /app/ 目录。

  5. 复制远程文件:

    COPY https://example.com/file.txt /app/

    从远程 URL 下载文件 file.txt 并复制到容器中的 /app/ 目录。

  6. 复制文件并更改权限:

    COPY --chown=user:group source.txt /app/destination.txt

    将主机上的 source.txt 文件复制到容器中的 /app/destination.txt,并将文件的所有者设置为 user,组设置为 group

  7. 复制文件到特定构建阶段:

    FROM builder as build
    COPY source.txt /app/destination.txt

    在多阶段构建中,将 source.txt 文件从 builder 阶段复制到 build 阶段的容器中。
    !!!

!!! warning 注意事项

  • 源文件路径
    • COPY 命令的第一个参数是源文件或目录的路径。
    • 在指定路径时,可以是相对于 Dockerfile 所在目录的相对路径,也可以是一个绝对路径
  • 目标路径
    • COPY 命令的第二个参数是目标路径,表示要将源文件或目录复制到容器中的位置。
    • 这个路径可以是容器内的绝对路径,也可以是相对于容器工作目录的路径。如果目标路径不存在,则会自动创建
  • 目录复制
    • 如果源路径是一个目录,COPY 命令将递归地复制该目录及其所有内容,但不复制目录自身
    • 目标路径必须是一个已存在的目录,或者在构建过程中已经创建。
  • 文件权限
    • 使用 COPY 命令复制文件时,文件的权限将保持不变
    • 如果需要更改文件的权限,可以使用 RUN 命令在 Dockerfile 中进行相应的权限更改操作。
  • 使用通配符
    • COPY 命令支持使用通配符来复制多个文件。
    • 例如,COPY *.txt /app/ 将复制所有以 .txt 结尾的文件到容器的 /app/ 目录。
  • 多个复制操作
    • 可以在 Dockerfile 中使用多个 COPY 命令来复制不同的文件或目录到容器中。
    • 这些复制操作将按照在 Dockerfile 中的顺序依次执行。
  • 文件排除
    • 可以使用 .dockerignore 文件来排除不需要复制到镜像中的文件和目录。
    • .dockerignore 文件的格式类似于 .gitignore 文件,可以通过添加规则来过滤文件和目录。

!!!

ADD

!!! note 基本信息

  • 用途
    • 支持将压缩文件进行复制解压
  • 格式
    ADD [--chown=<user>:<group>] <src>... <dest>
    ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]

!!!

!!! warning 注意事项

  • 如果是一个 URL ,下载后的文件权限自动设置为 600
  • 如果是一个本地文件系统上的打包文件,如: gz, bz2 ,xz ,它将被解包 ,其行为类似于"tar -x"命令, 但是通过URL获取到的tar文件不会自动展开
    !!!

CMD


!!! note 基本信息

  • 用途
    • 设置容器启动时要执行的默认命令
  • 格式
    # 使用 exec 执行,推荐方式,第一个参数必须是命令的全路径,此种形式不支持环境变量
    CMD ["executable","param1","param2"]
    
    # 在 /bin/sh 中执行,提供给需要交互的应用;此种形式支持环境变量
    CMD command param1 param2
    
    # 提供给 ENTRYPOINT 命令的默认参数
    CMD ["param1","param2"]

!!!

!!! tip 常见用法

  1. 执行单个命令:

    CMD echo "Hello, Docker!"

    在容器启动时执行 echo "Hello, Docker!" 命令。

  2. 执行可执行文件:

    CMD ./myapp

    在容器启动时执行名为 myapp 的可执行文件。

  3. 指定命令和参数:

    CMD ["python", "app.py"]

    在容器启动时执行 python app.py 命令。

  4. 使用 Shell 执行命令:

    CMD bash -c "echo Welcome; echo to Docker"

    在容器启动时使用 Shell 执行复杂的命令或命令序列。

  5. 覆盖 CMD:
    在运行容器时,可以使用 docker run 命令的参数来覆盖 CMD 命令。例如:

    docker run myimage echo "Hello, World!"

    这将在容器运行时覆盖默认的 CMD 命令,并执行 echo "Hello, World!"

  6. 作为ENTRYPOINT的参数:

    ENTRYPOINT ["echo", "Hello,"]
    CMD ["Docker!"]

!!!

!!! warning 注意事项

  1. 作为默认执行命令
    • dockerfile 里面没有ENTRYPOINT命令docker run没有指定执行命令时
  2. 最有最后一条生效
    • 如果在dockerfile 中添加多个 CMD命令,后添加的CMD命令将覆盖前面添加的
  3. 可以被替换
    • docker run运行容器的过程中,可以指定需要执行的命令,这个命令将替代dockerfile CMD命令
      !!!

ENTRYPOINT


!!! note 基本信息

  • 用途
    • 用于指定在容器启动时要执行的可执行命令或脚本
  • 格式
    # 使用 exec 执行
    ENTRYPOINT ["executable", "param1", "param2"...]
    # shell中执行
    ENTRYPOINT command param1 param2

!!!

!!! tip 常见用法

  • 运行环境配置

    FROM  rockylinux:9.3
    LABEL maintainer="alfiecheung <root@alfiecheung.com>"
    RUN sed -e 's|^mirrorlist=|#mirrorlist=|g' \
        -e 's|^#baseurl=http://dl.rockylinux.org/$contentdir|baseurl=https://mirrors.aliyun.com/rockylinux|g' \
        -i.bak /etc/yum.repos.d/rocky-*.repo 
    RUN dnf install -y nginx &&  rm -rf /var/cache/dnf/*
    
    COPY entry.sh /tmp
    RUN chmod a+x /tmp/entry.sh
    
    ENTRYPOINT ["/tmp/entry.sh"]
    CMD ["nginx", "-g", "daemon off;"]
    #!/bin/sh
    # 创建nginx配置文件
    # 变量可以使用默认变量值(即 :- 后的内容)
    # 或通过 ENV / docker run -e 提供变量内容进行覆盖
    cat > /etc/nginx/conf.d/custome.conf <<EOF
    server {
      server_name ${HOSTNAME:-"wwww.alopex.com"};
      listen ${IP:-"0.0.0.0"}:${PORT:-8080};
      root ${DOC_ROOT:-"/usr/share/nginx/html"};
    }
    EOF
    
    # 创建目录
    mkdir -p ${DOC_ROOT:-/usr/share/nginx/html}
    
    # 自定义主页
    echo ${HOSTNAME:-"www.alopex.com"} > ${DOC_ROOT:-/usr/share/nginx/html}/index.html
    
    # 通过exec接受CMD“参数”/ docker run “命令”
    # 由于exec 内建命令可替换当前shell,因此首命令可由用户指定需要执行的命令,而不仅仅只是参数传递
    # 提高了脚本的灵活性,是一个约定成俗的操作
    exec "$@"
    # 创建镜像
    docker build -t rocky-nginx:entry-v2 .
    
    # 启动容器
    ## 自定义hostname和port变量,能够在配置中修改
    docker run -d -e PORT=9090 \
    -e HOSTNAME="www.leslie.com" \
    -e DOC_ROOT="/tmp/cc" rocky-nginx:entry-v2
    
    # 测试容器
    curl ip.ip.ip.ip:9090

!!!

!!! warning 注意事项

  1. ENTRYPOINT接收docker run参数
    • docker run提供的命令无法替换ENTRYPOINT,相反该命令将作为参数传递给ENTRYPOINT
    • 参数优先级
      • docker run
      • CMD
  2. 最有最后一条生效
    • 如果在dockerfile 中添加多个 ENTRYPOINT命令,后添加的ENTRYPOINT命令将覆盖前面添加的
      !!!

ARG

!!! note 基本信息

  • 用途
    • Build 阶段指定变量
  • 格式
    • ARG <name>[=<default value>]
      !!!

!!! tip 常见用法

  • 与FROM结合,在构建时始终使用追新的images
    ARG CODE_VERSION=latest
    FROM base:${CODE_VERSION}

!!!

!!! warning 注意事项

  • 唯一可以放置在FROM命令前的指令
  • ARG指令在build 阶段指定变量
  • 和ENV不同的是,容器运行时并不存在ARG定义的环境变量
  • 可以用 docker build --build-arg <参数名>=<值> 来覆盖
    !!!

VOLUME

!!! note 基本信息

  • 用途
    • 创建匿名卷
    • 容器删除后默认将删除容器内数据,匿名卷是数据持久话的一个实现手段
    • 持久化可以使得容器在删除后,挂载的匿名卷目录将继续保留
    • 更多详细内容 0x06 docker/存储管理
  • 格式
    VOLUME <容器内路径>
    VOLUME ["<容器内路径1>", "<容器内路径2>"...]
    注意:
    <容器内路径>如果在容器内不存在,在创建容器时会自动创建
    <容器内路径>如果是存在的,同时目录内有内容,将会把此目录的内容复制到宿主机的实际目录

!!!

!!! tip 常见用法

  • 挂载两个匿名卷
    • VOLUME [ "/data1","/data2" ]
      !!!

!!! warning 注意事项

  1. 匿名卷默认路径/var/lib/docker/volumes
  2. 数据存储目录 /var/lib/docker/volumes/<container-id>/_data
  3. 匿名卷创建宿主机和镜像都不需要要事先存在真实目录
  4. 挂载的匿名卷目录将在容器内自动创建
  5. 匿名卷无有效名称虽然可保留数据复用性不强,容器删除后难以获取卷名称 (即数据保留的匿名卷)
    • 容器挂载卷名称获取: docker inspect --format '{{range .Mounts}}{{.Name}}{{end}}' <container-id>
    • 名称例子:9bcb9d85be8480d83e31ba6f08ba08c5669220c424a6313b318b2850e24353ba
      !!!

EXPOSE

!!! note 基本信息

  • 用途
    • 用于启动容器时,端口暴露的标识
  • 格式
    EXPOSE <port>[/ <protocol>] [<port>[/ <protocol>] ..]

!!!

!!! tip 常见用法

  • 暴露特定端口和协议
    • EXPOSE 11211/udp 11211/tcp
      !!!

!!! warning 注意事项

  1. EXPOSE仅仅只是一个便捷标识,并不意味这容器就使用其暴露的端口
  2. EXPOSE主要是和—P临时端口映射配合使用,使用端口并非一定需要通过该语句暴露,也可以使用-p host-port:container-port
    !!!

WORKDIR

!!! note 基本信息

  • 用途
    • 指定工作目录
    • 为后续的 RUN, CMD, ENTRYPOINT 指令配置工作目录,当容器运行后,进入容器内WORKDIR指定的默认目录
  • 格式

!!!

!!! tip 常见用法

  • 指定当前的工作目录
    • WORKDIR /path/to/workdir
      !!!

!!! warning 注意事项

  1. 指定存在的workdir将会被自动创建
  2. 在RUN可以生效,在CMD、ENTRYPOINT可能会有问题
    !!!

ONBUILD

!!! note 基本信息

  • 用途
    • 子镜像调用父镜像是执行的命令
  • 格式
    • ONBUILD [INSTRUCTION]
      !!!

!!! tip 常见用法

  • 通过该父镜像创建的子镜像都需要打上标签
    • ONBUILD RUN echo "alopex copyright C" > /etc/parent-os
      !!!

!!! warning 注意事项

  1. ONBUILD不能自我能套,且不会触发FROM和MAINTAINER指令
  2. 推荐在标签中注明,例如 ruby:1.9-onbuild
  3. ONBUILD命令只能实现单次传递(直接继承的子代),不会持续传递(间接继承的子代)
    !!!

USER

!!! note 基本信息

  • 用途
    • 指定默认的容器运行用户名称或UID
    • 后续dockerfile中的 RUN ,CMD和ENTRYPOINT指令时使用此用户
  • 格式
    USER <user>[:<group>]
    USER <UID>[:<GID>]

!!!

!!! tip 常见用法

  • 为数据库用户创建musql用户
    RUN groupadd -r mysql && useradd -r -g mysql mysql
    USER mysql

!!!

!!! warning 注意事项

!!!

HEALTHCHECK

!!! note 基本信息

  • 用途
    • 容器启动后的状态检测,确认容器是否按照预订要求运行
  • 格式
    HEALTHCHECK [选项] CMD <命令> #设置检查容器健康状况的命令,如果命令执行失败,则返回1,即 unhealthy
    HEALTHCHECK NONE #如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令
    
    HEALTHCHECK 支持下列选项:
    --interval=<间隔> #两次健康检查的间隔,默认为 30 秒
    --timeout=<时长> #健康检查命令运行超时时间,如果超过这个时间,本次健康检查就被视为失败,默认 30 秒
    --retries=<次数> #当连续失败指定次数后,则将容器状态视为 unhealthy,默认3次
    --start-period=<FDURATION> #default: 0s 
    
    #检查结果返回值:
    0  #success the container is healthy and ready for use
    1  #unhealthythe container is not working correctly
    2  #reserveddo not use this exit code

!!!

!!! tip 常见用法

  • 检测80请求是否正常
    HEALTHCHECK --interval=5s --timeout=3s CMD curl -fs http://127.0.0.1:90/

!!!

!!! warning 注意事项

  1. healthcheck 是认为设定检测规则,unhealthy表示检测状态异常但不代表容器服务不可用
  2. 对于启动时间较长的容器,建起增大timeout时间
  3. 容器检查会造成额外的内部资源消耗
    !!!

.dockerignore 文件

!!! note 基本信息

  • 用途
    • 生成构建上下文时Docker客户端忽略指定模式文件和文件夹
  • 格式
    #	#以#开头的行为注释
    *	#匹配任何非分隔符字符序列
    ?	#匹配任何单个非分隔符
    \\	#表示
    **	#匹配任意数量的目录(包括零)例如,**/*.go将排除在所有目录中以.go结尾的所有文件,包括构建上下文的根。
    !	#表示取反,可用于排除例外情况

!!!

!!! tip 常见用法

#排除 test 目录下的所有文件
test/*
#排除 md 目录下的 xttblog.md 文件
md/xttblog.md
#排除 xttblog 目录下的所有 .md 的文件
xttblog/*.md
#排除以 xttblog 为前缀的文件和文件夹
xttblog?
#排除所有目录下的 .sql 文件夹
**/*.sql

!!!

!!! warning 注意事项

  • 通过创建.dockerignore文件实现
    !!!

Docker 网络模式

默认网络.

容器间通信

  • 容器之间默认互联互通,使用参数--icc=true
  • 修改容器之间不互联互通
    • 启动文件修改 /usr/lib/systemd/system/docker.service
      • ExecStart=usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --icc=false
      • systemctl daemon-reload && systemctl restart docker
    • 配置文件修改 /etc/docker/daemon.json
      {
        "icc": false
      }

自定义IP段

  • 默认IP段:172.17.0.1/16
  • 查看默认网段
    • ip addr show docker0

    • docker network inspect <bridge-name>

  • 修改方式
    • 启动文件修改 /usr/lib/systemd/system/docker.service
      • ExecStart=usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --bip=192.168.100.1/24
      • systemctl daemon-reload && systemctl restart docker
    • 配置文件修改 /etc/docker/daemon.json
      {
          "bip": "192.168.100.1/24"
      }

自定义网桥

  • 默认网桥名称:docker0
  • 内容查看
    • brctl show
  • 自定义网桥
    # 自定义网桥 my-br0
    brctl addbr my-br0 
    
    # 为网桥设定IP地址段 192.168.100.1/24
    ip a a 192.168.100.1/24 dev my-br0
  • 默认网桥修改
    • 配置文件 ``
    • 启动文件 /lib/systemd/system/docker.service
      • ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -b my-br0

容器间互联

让数据库和wordpress两个容器实现互联

!!! info 互联方式

  • 环境准备

    mkdir -p /tmp/cc/lamp_docker/mysql
    mkdir -p /tmp/cc/{mysql,wordpress}
    
    cat > lamp_docker/env_mysql.list <<EOF
    MYSQL_ROOT_PASSWORD=alopex
    MYSQL_DATABASE=wordpress
    MYSQL_USER=wpuser
    MYSQL_PASSWORD=alopex
    EOF
    
    cat > lamp_docker/env_wordpress.list <<EOF
    WORDPRESS_DB_HOST=mysql:3306  # 此处 mysql为容器名称,将被接写为IP地址在(/etc/hosts中被定义)
    WORDPRESS_DB_NAME=wordpress
    WORDPRESS_DB_USER=wpuser
    WORDPRESS_DB_PASSWORD=alopex
    WORDPRESS_TABLE_PREFIX=wp_
    EOF
    
    cat > lamp_docker/mysql/mysql_test.cnf <<EOF
    [mysqld]
    server-id=100
    log-bin=mysql-bin
    EOF
    
    tree /tmp/cc/
    /tmp/cc/
    ├── lamp_docker
    │   ├── env_mysql.list
    │   ├── env_wordpress.list
    │   └── mysql
    │       └── mysql_test.cnf
    ├── mysql
    └── wordpress
    
    3 directories, 3 files
  • 名称互联

    • 使用--link选项实现容器名称的引用

    • 其本质为在容器内的/etc/hosts中添加--link后指定的容器的IP和主机名的对应关系,从而实现名称解析

    • 格式

      --link list   #Add link to another container
      
      格式:
      docker run --name <容器名称>    #先创建指定名称的容器
      docker run --link <目标通信的容器ID或容器名称>  #再创建容器时引用上面容器的名称
    • 例子

      docker run --name mysql \
      -d -p 3306:3306 \
      -v /tmp/cc/mysql:/var/lib/mysql \
      -v /tmp/cc/lamp_docker/mysql/:/etc/mysql/conf.d  \
      --env-file=/tmp/cc/lamp_docker/env_mysql.list \
      mysql:8.0
      
      # 前端容器使用名称互联连接到mysql,
      # 当前端需要访问mysql时,可通过其名称(mysql)访问,解决IP漂移问题
      docker run --name wordpress \
      -d -p 80:80 \
      --link mysql \
      -v /tmp/cc/wordpress:/var/www/html/wp-content \
      --env-file=/tmp/cc/lamp_docker/env_wordpress.list \
      wordpress:php7.4-apache 


      由于配置已经在容器阶段完成,因此登录页面填写好信息后,即会跳转到登录页面

  • 别名互联

    • 容器名称是自身的一个特性,容器可对其进行修改,因此具备不稳定性

    • 客户容器如果需要调用容器,应该为其配置一个别名

    • 这样可以保证被引用容器修改名称时,不影响调用容器对被引容器名称的继续使用

    • 格式

      # 先创建指定名称的容器
      docker run --name <容器名称>
      
      #给上面创建的容器起别名,来创建新容器
      docker run --name <容器名称> --link <目标容器名称>:"<容器别名1> <容器别名2> ..."
    • 实例

      # 创建容器A,别名为 demo
      docker run -d --name demo rocky:demo tail -f /etc/hosts
      
      # 创建容器B,关联容器A的别名 (A的别名为 my-demo)
      docker run -d --name client --link demo:"my-demo" rocky:demo tail -f /etc/hosts
      
      # 查看容器B上的hosts
      docker exec client cat /etc/hosts
      127.0.0.1	localhost
      ::1	localhost ip6-localhost ip6-loopback
      fe00::0	ip6-localnet
      ff00::0	ip6-mcastprefix
      ff02::1	ip6-allnodes
      ff02::2	ip6-allrouters
      172.17.0.2	my-demo 1330796cbbdc demo
      172.17.0.3	474584380ed6
      
      # 修改容器A的名称 为 new-demo
      docker rename demo new-demo
      
      # 容器B ping 容器A别名 my-demo 依然生效
      docker exec -it client /bin/bash
      ping my-demo
      PING my-demo (172.17.0.2) 56(84) bytes of data.
      64 bytes from my-demo (172.17.0.2): icmp_seq=1 ttl=64 time=0.160 ms
      64 bytes from my-demo (172.17.0.2): icmp_seq=2 ttl=64 time=0.108 ms
      ...

!!!

网络连接模式.

  • 模式语法
    docker run --network <mode>
    docker run --net=<mode>
    <mode>:
        none
        bridge
        host
        container:<容器名或容器ID>
        <自定义网络名称>

Bridge (桥接模式)

!!! tip 场景说明

  • 语法声明

    • docker run --network= [docker0 | my-bridge] ...
  • 工作方式

    • 宿主机上创建默认的桥接器docker0,创建容器时将为容器创建veth并将该接口关联至桥接器上
  • 配置查看

  • 本质

    • 通过启用ipforward实现包在主机内转发

      • cat /proc/sys/net/ipv4/ip_forward
    • 通过iptables NAT chaindocker0网段IP进行SNAT实现与外部网络通信

    • 实例说明,nginx容器内开启80端口,且使用宿主机49153端口

      docker port dazzling_margulis
      80/tcp -> 0.0.0.0:49153
      80/tcp -> :::49153
      # PREROUTING 的 NAT 表转发
      # 目的地址是本机的数据包,都转发给 DOCKER 链处理
      sudo iptables -t nat -nL PREROUTING
      Chain PREROUTING (policy ACCEPT)
      target     prot opt source               destination         
      DOCKER     all  --  0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL
      
      # DOCKER 链的内容
      # RETURN 规则:对于不匹配任何其他规则的数据包,应该立即返回到调用链的上一级
      # DNAT 规则: 对于匹配 tcp协议目的端口 49153 的流量,转发到 172.17.0.2 主机的 80 端口
      sudo iptables -t nat -L DOCKER
      Chain DOCKER (2 references)
      target     prot opt source               destination         
      RETURN     all  --  anywhere             anywhere            
      DNAT       tcp  --  anywhere             anywhere             tcp dpt:49153 to:172.17.0.2:80
      
      # MASQUERADE 改写包来源 IP 为防火墙 网卡 IP
      # 功能与 SNAT 略有不同,当进行 IP 伪装时,不需指定要伪装成哪个 IP,IP 会从网卡直接读取
      sudo iptables -t nat -nvL POSTROUTING | column -t  | awk 'NR >1 {print}'
      pkts   bytes        target      prot    opt   in        out       source         destination       
      0      0            MASQUERADE  all     --    *         !docker0  172.17.0.0/16  0.0.0.0/0         
      0      0            MASQUERADE  tcp     --    *         *         172.17.0.2     172.17.0.2   tcp  dpt:80
      
      # 查看路由表
      # 对于172.17.0.0网段,通过docker0接口访问
      route  -n | column -t | awk 'NR >1 {print}'
      Destination   Gateway         Genmask        Flags  Metric  Ref  Use  Iface
      0.0.0.0       172.16.102.254  0.0.0.0        UG     600     0    0    wlp5s0
      169.254.0.0   0.0.0.0         255.255.0.0    U      1000    0    0    wlp5s0
      172.16.102.0  0.0.0.0         255.255.255.0  U      600     0    0    wlp5s0
      172.17.0.0    0.0.0.0         255.255.0.0    U      0       0    0    docker0
  • 配置参数

    {
    "hosts": ["tcp://0.0.0.0:2375", "fd://"],
    "bip": "192.168.100.100/24",        #分配docker0网卡的IP
    "fixed-cidr": "192.168.100.128/26", #分配容器IP范围,26不是容器IP的子网掩码,只表示地址范围
    "fixed-cidr-v6": "2001:db8::/64",
    "mtu": 1500,
    "default-gateway": "192.168.100.200", #网关必须和bip在同一个网段
    "default-gateway-v6": "2001:db8:abcd::89",
    "dns": [ "1.1.1.1", "8.8.8.8"]
    }
  • 通信

    • 内网 (默认可达)
      • 容器间通信由网桥的icc参数决定
        • "com.docker.network.bridge.enable_icc": "true"
      • 宿主机与容器的联通性由bridge的路由决定
    • 外网 (默认可达)
      • 外网的通信由 iptable 的 SNAT规则决定
  • 特点

    • 缺省默认配置: 容器默认自动获取172.17.0.0/16的IP地址,此地址可以修改
    • 访问外网: 利用宿主机的物理网卡,SNAT连接外网
    • 外部主机无法直接访问容器: 可以通过配置DNAT接受外网的访问
    • 低性能较低: 通过NAT转换有转换消耗
    • 端口管理繁琐: 每个容器必须手动指定唯一的端口容器产生端口冲容
  • 小结

    • Bridge (桥接)是默认网络链接模式,可实现内网和外网的通信
    • 适用于希望容器之间相互通信,并且与外部网络隔离的场景
      !!!

Host (主机模式)

!!! tip 场景说明

  • 语法声明
    • docker run --network=host ...
  • 工作方式
    • 共享网络资源,访问主机地址即访问容器
  • 配置查看
  • 本质
    • 宿主机共享网络地址、端口等信息,即不对容器进行网络命名空间资源进行隔离
  • 通信
    • 内网 (无)
    • 外网
      • 跨主机间通信,只要能与宿主机通信即可访问容器
      • 宿主机可访问外网的前提下,容器可访问外网
  • 特点
    • 使用参数 --network host 指定
    • 共享宿主机网络,各容器网络无隔离
    • 网络性能无损耗
    • 网络故障排除相对简单
    • 容易产生端口冲突
    • 网络资源无法分别统计
    • 不支持端口映射
  • 小结
    • 适用于希望容器直接使用主机网络栈,与主机共享网络的场景
      !!!

none (无网络)

!!! tip 场景说明

  • 语法声明
    • docker run --network=none ...
  • 工作方式
    • 将容器置于一个隔离的网络环境中,该环境没有任何网络连接。
  • 内容查看
  • 本质
    • 在容器运行时禁用容器的网络功能,使得容器无法进行网络通信
  • 通信
    • 内网 (无)
    • 外网 (无)
  • 特点
    • 使用参数 --network none 指定
    • 默认无网络功能,无法和外部通信
    • 无法实现端口映射
    • 适用于测试环境
  • 小结
    • 适用于不需要网络连接的容器,用于隔离容器与网络的场景
      !!!

container (容器网络)

!!! tip 场景说明

  • 语法声明
    • docker run --net=container:mycontainer ...
  • 工作方式
    • 创建容器时,需要关联指定容器,并与该容器共享网络资源
    • 端口不能和被指定容器的端口冲突,除了网络之外的文件系统、进程信息等仍然保持相互隔离
    • 两个容器的进程可以通过lo网卡进行通信
  • 本质
    • 新建的容器与被指定的容器网络资源共享,其他NS资源保持独立
  • 通信
    • 内网 (与关联容器保持一致)
    • 外网 (与关联容器保持一致)
  • 特点
    • 使用参数 --network container:名称ID 指定
    • 与宿主机网络空间隔离
    • 容器间共享网络空间,直接使用对方的网络
    • 第一个容器的网络可能是bridge, none, host,而第二个容器模式依赖于第一个容器
    • 如果第一个容器停止,将导致无法创建第二个容器
    • 第二个容器可以直接使用127.0.0.1访问第一个容器
    • 适合频繁的容器间的网络通信
    • 默认不支持端口映射,较少使用
  • 小结
    • 适用于希望多个容器共享相同网络栈,直接通信的场景。
  • 案例
    # 创建前端容器 wordpress,开放宿主机端口80
    docker run -d \
    -p 80:80 --name wordpress \
    -v /data/wordpress:/var/www/html \
    wordpress:php7.4-apache
    
    # 创建数据库容器 mysql,共享前端wordpress的网络
    # 由于使用了 --network,后续链接数据库可使用 127.0.0.1
    docker run --network container:wordpress \
    -e MYSQL_ROOT_PASSWORD=alopex \
    -e MYSQL_DATABASE=wordpress \
    -e MYSQL_USER=wordpress \
    -e MYSQL_PASSWORD=alopex \
    -v /data/mysql:/var/lib/mysql \
    --name mysql -d \
    mysql:8.0

    !!!

自定义网络

!!! tip 场景说明

  • 语法声明
    docker network create -d <mode> --subnet <CIDR> --gateway <网关> <自定义网络名称>
    
    # 注意mode不支持host和none 默认是bridge模式
    -d <mode> 可省略,默认为bridge
    • docker run --net= my-network ...
  • 工作方式
    • 使用自定义网络模式, 实现不同集群应用的独立网络管理, 而互不影响在网一个网络内, 可以直接利用容器名相互访问
  • 案例
    # 创建一个subnet 选择使用桥接模式,网段为 172.27.0.0/16
    docker network create -d bridge \
    --subnet=172.27.0.0/16 \
    --gateway=172.27.0.1 mynet
    
    # 查看自建网络
    [
        {
            "Name": "mynet",
            "Id": "38214b8ba881d2b919bf59c1e5e27d838c973967bd04b4456333388a93c1bc18",
            "Created": "2024-04-26T16:10:55.214517178+08:00",
            "Scope": "local",
            "Driver": "bridge",
            "EnableIPv6": false,
            "IPAM": {
                "Driver": "default",
                "Options": {},
                "Config": [
                    {
                        "Subnet": "172.27.0.0/16",
                        "Gateway": "172.27.0.1"
                    }
                ]
            },
            "Internal": false,
            "Attachable": false,
            "Ingress": false,
            "ConfigFrom": {
                "Network": ""
            },
            "ConfigOnly": false,
            "Containers": {},
            "Options": {},
            "Labels": {}
        }
    ]
    # 创建容器使用自定义网络
    docker run --network=mynet -d rocky:demo tail -f /etc/hosts
    
    # 查看其网络配置
    "Networks": {
        "mynet": {
            "IPAMConfig": null,
            "Links": null,
            "Aliases": [
                "75be6bd6aaf4"
            ],
            "NetworkID": "38214b8ba881d2b919bf59c1e5e27d838c973967bd04b4456333388a93c1bc18",
            "EndpointID": "89fd76bd5dd18ac24f89b498d3336901058171ec817eae905b7fc9c1eb5b3e55",
            "Gateway": "172.27.0.1",
            "IPAddress": "172.27.0.2",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "MacAddress": "02:42:ac:1b:00:02",
            "DriverOpts": null
        }

!!!

Harbor私有仓库

基本操作

上传镜像

  1. harbor创建项目和用户

    • 创建项目 Projects
    • 创建用户 Administration -> User
    • 将现有用户alfie成为项目member赋予权限Project Admin
  2. 登录harbor

  3. 本地镜像打标签

    • 标签格式
      • Harbor-host:port/project-name/image:tag
      • 端口不能省略
    • docker tag alpine:latest 192.168.66.101:80/alfie-app/alpine:v1
  4. insecurity设置

    {
     "insecure-registries": ["10.0.0.10:80","10.0.0.11:80"]  #说明: ":80"端口可省略
    }
    
    systemctl daemon-reload
    systemctl restart docker
  5. 上传镜像

    • docker push 192.168.66.101:80/alfie-app/alpine:v1
  6. harbor查看镜像

  7. 查看上传日志

下载镜像

  1. docker security 开启(对于非443服务)

    {
     "insecure-registries": ["10.0.0.10:80","10.0.0.11:80"]  #说明: ":80"端口可省略
    }
    OR 
    /usr/lib/systemd/system/docker.service
    ExecStart=/usr/bin/dockerd --containerd=/run/containerd/containerd.sock --insecure-registry 192.168.66.101
    
    systemctl daemon-reload
    systemctl restart docker
  2. 登录harbor

  3. 拉去镜像

    • docker pull 192.168.66.101:80/alfie-app/alpine@sha256:6457d53fb065d6f250e1504b9bc42d5b6c65941d57532c072d929dd0628977d0

更新配置

  1. 关闭harbor
    cd /apps/harbor && docker-compose down

  2. 修改harbor配置文件 harbor.yml

  3. 配置重新生成

    ./prepare
    Clearing the configuration file: /config/portal/nginx.conf
    Clearing the configuration file: /config/log/logrotate.conf
    Clearing the configuration file: /config/log/rsyslog_docker.conf
    Clearing the configuration file: /config/nginx/nginx.conf
    Clearing the configuration file: /config/core/env
    Clearing the configuration file: /config/core/app.conf
    Clearing the configuration file: /config/registry/passwd
    Clearing the configuration file: /config/registry/config.yml
    Clearing the configuration file: /config/registry/root.crt
    Clearing the configuration file: /config/registryctl/env
    Clearing the configuration file: /config/registryctl/config.yml
    Clearing the configuration file: /config/db/env
    Clearing the configuration file: /config/jobservice/env
    Clearing the configuration file: /config/jobservice/config.yml
    Generated configuration file: /config/portal/nginx.conf
    Generated configuration file: /config/log/logrotate.conf
    Generated configuration file: /config/log/rsyslog_docker.conf
    Generated configuration file: /config/nginx/nginx.conf
    Generated configuration file: /config/core/env
    Generated configuration file: /config/core/app.conf
    Generated configuration file: /config/registry/config.yml
    Generated configuration file: /config/registryctl/env
    Generated configuration file: /config/registryctl/config.yml
    Generated configuration file: /config/db/env
    Generated configuration file: /config/jobservice/env
    Generated configuration file: /config/jobservice/config.yml
    loaded secret from file: /data/secret/keys/secretkey
    Generated configuration file: /compose_location/docker-compose.yml
  4. 启动harbor
    docker-compose up -d

https请求实现.

  1. 配置域名

hostnamectl set-hostname www.my-harbor.com
sed -i '$a 192.168.66.101 www.my-harbor.com' /etc/hosts

  1. 生成证书
    0x07 SSL/签署证书#制作根证书
    0x07 SSL/签署证书#生成服务端证书

    #创建证书相关数据的目录
    mkdir -p /data/harbor/certs
    cd /data/harbor/certs
    
    #生成ca的私钥
    openssl genrsa -out ca.key 4096
    
    #生成ca的自签名证书
    openssl req -x509 -new -nodes -sha512 -days 3650 \
    -subj "/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=ca.harbor.com" \
    -key ca.key \
    -out ca.crt
    
    #生成harbor主机的私钥
    openssl genrsa -out my-harbor.key 4096
    
    #生成harbor主机的证书申请
    openssl req -sha512 -new \
    -subj "/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=www.my-harbor.com" \
    -key my-harbor.key \
    -out my-harbor.csr
    
    #创建x509 v3 扩展文件(新版新增加的要求)
    cat > v3.ext <<-EOF
    authorityKeyIdentifier=keyid,issuer
    basicConstraints=CA:FALSE
    keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
    extendedKeyUsage = serverAuth
    subjectAltName = ip:192.168.66.101, DNS:www.my-harbor.com
    
    #[alt_names]
    #DNS.1=www.my-harbor.com      #此处必须和和harbor的网站名称一致
    #DNS.2=my-harbor.com                 #可选
    EOF
    
    #给 harbor主机颁发证书
    openssl x509 -req -sha512 -days 3650 \
    -extfile v3.ext \
    -CA ca.crt -CAkey ca.key -CAcreateserial \
    -in my-harbor.csr \
    -out my-harbor.crt
    
    # 证书查看
    openssl x509 -in my-harbor.crt -noout -text
  2. 服务器使用证书

    # 在应用下创建证书目录
    mkdir  /apps/harbor/certs
    
    # 复制证书到该路径下
    cp my-harbor.crt my-harbor.key /apps/harbor/certs/
    
    # 修改配置 harbor.yml
    https:
      # https port for harbor, default is 443
      port: 443
      # The path of cert and key files for nginx
      certificate: /apps/harbor/certs/my-harbor.crt
      private_key: /apps/harbor/certs/my-harbor.key
      
    # 使配置生效
    cd /apps/harbor/
    ./prepare
    docker-compose down -v
    docker-compose up -d
  3. 客户端使用证书

  4. 浏览器使用证书

  • c:\Windows\System32\Drivers\etc\hosts
    • 追加主机解析记录
    • 192.168.66.101 www.my-harbor.com

    • *
  • 证书导入
  • 再次访问
  1. 客户端配置证书

    # 转换客户端证书(即后缀为 my-harbor.cert)
    cd /data/harbor/certs
    openssl x509 -inform PEM -in my-harbor.crt -out my-harbor.cert
    
    # 创建和harbor服务器同名目录
    mkdir -pv /etc/docker/certs.d/www.my-harbor.com/
    
    # 将.cert, .key, ca.key 复制到该目录下
    cp my-harbor.cert my-harbor.key ca.crt /etc/docker/certs.d/www.my-harbor.com/
  2. 推送镜像测试

    • 登录账号
      • docker login www.my-harbor.com
    • 修改镜像标签
      • docker tag busybox:latest www.my-harbor.com/alfie-app/busybox:v1
    • 推送镜像
      • docker push www.my-harbor.com/alfie-app/busybox:v1
    • 获得镜像
      • docker pull www.my-harbor.com/alfie-app/busybox@sha256:db16cd196b8a37ba5f08414e6f6e71003d76665a5eac160cb75ad3759d8b3e29

JumpServer安装和使用

部署

离线部署

离线部署介绍

脚本部署

curl -sSL https://resource.fit2cloud.com/jumpserver/jumpserver/releases/latest/download/quick_start.sh | bash

!!! tip 密钥和token信息

1. Configure Private Key
SECRETE_KEY:     216aa1a921346036377a317f007a50330c84a85dea56d145
BOOTSTRAP_TOKEN: jz0nNnx1Kts9v45233O8bHbZ
complete

# 应对此进行备份,因迁移请保证 SECRET_KEY和BOOTSTRAP_TOKEN与旧环境一致

!!!

!!! tip 提示信息
首次安装后需要修改配置文件,定义 DOMAINS 字段后即可正常使用。
如果服务器是一键安装并且旧版本就已经使用 JumpServer 开启了 HTTPS,则不需要进行任何更改。
需要使用 IP 地址来访问 JumpServer 的场景,可以根据自己的 IP 类型来填写 config.txt 配置文件中 DOMAINS 字段为公网 IP 还是内网 IP。

默认安装路径:/opt/jumpserver

vim /opt/jumpserver/config/config.txt 

# 可信任 DOMAINS 定义,
# 定义可信任的访问 IP, 请根据实际情况修改, 如果是公网 IP 请改成对应的公网 IP,
# DOMAINS="demo.jumpserver.org"    # 使用域名访问
# DOMAINS="172.17.200.191"         # 使用 IP 访问
# DOMAINS="demo.jumpserver.org,172.17.200.191"    # 使用 IP 和 域名一起访问
DOMAINS="www.my-harbor.com,192.168.66.101:80"

!!!

访问方式

!!! info 访问登录

地址: http://<JumpServer服务器IP地址>:<服务运行端口>
如上面配置:http://www.my-harbor.com:80
用户名: admin
密码: admin

!!!

服务管理

/opt/jumpserver-installer-v3.10.9/jmsctl.sh

JumpServer Deployment Management Script

Usage: 
  ./jmsctl.sh [COMMAND] [ARGS...]
  ./jmsctl.sh --help

Installation Commands: 
  install           Install JumpServer

Management Commands: 
  config            Configuration  Tools
  start             Start     JumpServer
  stop              Stop      JumpServer
  restart           Restart   JumpServer
  status            Check     JumpServer
  down              Offline   JumpServer
  uninstall         Uninstall JumpServer

More Commands:
  load_image        Loading docker image
  backup_db         Backup database
  restore_db [file] Data recovery through database backup file
  raw               Execute the original docker-compose command
  tail [service]    View log

常用功能

管理员

创建用户组

配置用户 (登录名称 leslie)

创建资产



账户模板

账户推送



用户登录

创建授权策略

命令执行限制


操作员

登录账户




webshell登录用户


webshell命令限制


审计员

会话查看




命令记录



查看录制视频

  • 对于下载的是视频,我们需要用特定的工具对其进行打开
  • VideoPlayer

登录日志

操作日志

改密日志