Docker学习笔记
系统学习 Docker 0 347

基本原理

  • Docker将应用的Libs(函数库)、Deps(依赖)、配置与应用一起打包,形成可移植镜像【解决大型项目依赖关系复杂导致的兼容性问题】
  • 将每个应用放到容器去运行,避免互相干扰【容器本质上是一个运行在沙盒中的隔离进程,由Linux系统本身负责隔离】
  • Docker将用户程序与所需要调用的系统库函数一起打包,仅依赖系统内核,因此可以在任意Linux操作系统上运行【解决环境不一致问题】

常见命令

推荐使用新版本的命令结构:

docker <object> <command> <options>
  1. <object>表示将要操作的Docker对象的类型,可以是container, image, network或者volume
  2. <command>表示守护程序要执行的任务,例如run, ls, stop
  3. <options>可以是任何可以覆盖命令默认行为的有效参数,例如端口映射的--publish选项

镜像操作

  • 拉取镜像
    docker image pull <repository>:<tag>
  • 展示镜像
    docker image ls
  • 添加标记
    docker image tag <image id>/<old repository>:<old tag> <new repository>:<new tag>
  • 删除镜像
    • 删除指定的镜像
      docker image rm <repository>:<tag>
    • 清除未被使用的悬空镜像(没有与任何标签关联的镜像)
      docker image prune [-a] [-f]
      • -f: 跳过询问
      • -a: 清除所有未被使用的镜像,包含有标签但未使用的镜像
  • 构建镜像
    docker image build --tag <repository>:<tag> .
  • 镜像导入导出
    docker image save -o my_image.tar my_image
    docker image load -i my_image.tar

容器操作

  • 启动容器
    • 分离式 + 端口映射 + 目录映射
      docker container run --detach --publish 8080:80 --volume $(pwd):/zone --name containerName fhsinchy/hello-dock
    • 分离式 + 停止后立刻被删除 + 端口映射 + 目录映射
      docker container run --rm --detach --publish 8888:80 --name containerName fhsinchy/hello-dock
    • 停止后立刻删除 + 启动命令(一般用快速执行操作)
      docker container run --rm busybox echo -n my-secret | base64
      • 镜像名称后传递的任何内容都将传递到镜像的默认入口里
    • 交互式 (测试命令)
      docker container run -it fhsinchy/hello-dock
  • 执行命令
    docker container exec -it containerName echo 123
  • 查看IP地址
    docker container inspect 6fc954a21ad6 | grep IPAddress
  • 查看日志
    docker container logs [-f] containerName
    • -f--follow用于动态加载日志
  • 显示容器
    docker container ls [--all]
    • 不加-a-all只显示运行中的容器
  • 重命名容器
    docker container rename containerName1 containerName2
  • 暂停/恢复/停止/启动/重启
    • 停止容器
      docker container stop containerName
      docker container start containerName
    • 暂停/恢复容器
      docker container pause containerName
      docker container unpause containerName
    • 重启容器
      docker container restart containerName
  • 删除容器
    • 删除指定的容器
      docker container rm 6cf52771dde1
    • 删除所有停止的容器
      docker container prune [-f] 
  • 创建但不运行
    docker container create --publish 8080:80 fhsinchy/hello-dock
    docker container start containerName

docker execdocker run

首先看命令的--help的说法:

  • docker run: Create and run a new container from an image
    • -d: Run container in background and print container ID
    • -i: Keep STDIN open even if not attached
    • -t: Allocate a pseudo-TTY
  • docker exec: Execute a command in a running container
    • -d: Detached mode: run command in the background
    • -i: Keep STDIN open even if not attached
    • -t: Allocate a pseudo-TTY

显然,-d的差别很容易区分,即一个是针对容器,另一个是针对命令。

docker run一般只需要-d参数就可以在后台启动镜像中的服务,但有的时候,镜像内并没有设置启动命令,run的时候也无法找到合适的命令,就同时需要设置-i或者-t来让默认的/bin/bash/持续运行,来确保容器不退出。

数据卷操作

数据卷本质上就是docker默认的一个用于目录映射的路径

  • 创建数据卷
    docker volume create volumeName
  • 显示数据卷
    docker volume ls
  • 删除数据卷
    • 删除指定的数据卷
      docker volume rm volumeName [-f]
    • 删除不用的数据卷
      docker volume prune [-a] [-f]
      • -a用来删除所有不用的数据卷,而不只删除匿名的
  • 查看数据卷
    docker volume inspect henry529_mysql_data
    -----------------------------------------------
    [
        {
            "CreatedAt": "2024-01-30T14:03:27Z",
            "Driver": "local",
            "Labels": {
                "com.docker.compose.project": "henry529",
                "com.docker.compose.version": "2.24.3",
                "com.docker.compose.volume": "mysql_data"
            },
            "Mountpoint": "/var/lib/docker/volumes/henry529_mysql_data/_data",
            "Name": "henry529_mysql_data",
            "Options": null,
            "Scope": "local"
        }
    ]

其他操作

  • 清空数据
    docker system prune [-a] [-f] [-v]
    • 停止的容器: 所有已停止运行的容器将被自动删除
    • 未使用的镜像: 只有未被任何容器使用的悬挂镜像才会被删除;如果使用了-a或—all参数,所有未被使用的镜像都将被删除
    • 未使用的网络: 所有未被容器使用的自定义网络将被自动删除
    • 未使用的卷: 如果使用了-v—-volumes,所有未被容器引用的卷将被删除
    • 镜像缓存和Build缓存: 这些资源可能会占用大量磁盘空间,也会被清理
  • 查看启动命令
    docker inspect --format='{{json .Config.Cmd}}' containerName/imageName

镜像构建

  • 编写构建文件
    • 基本构建
      FROM ubuntu:latest
      RUN apt-get update && \
          apt-get install build-essential\ 
                          libpcre3 \
                          libpcre3-dev \
                          zlib1g \
                          zlib1g-dev \
                          libssl-dev \
                          -y && \
          apt-get clean && rm -rf /var/lib/apt/lists/*
      ARG FILENAME="nginx-1.19.2"
      ARG EXTENSION="tar.gz"
      ADD https://nginx.org/download/${FILENAME}.${EXTENSION} .
      RUN tar -xvf ${FILENAME}.${EXTENSION} && rm ${FILENAME}.${EXTENSION}
      RUN cd ${FILENAME} && \
          ./configure \
              --sbin-path=/usr/bin/nginx \
              --conf-path=/etc/nginx/nginx.conf \
              --error-log-path=/var/log/nginx/error.log \
              --http-log-path=/var/log/nginx/access.log \
              --with-pcre \
              --pid-path=/var/run/nginx.pid \
              --with-http_ssl_module && \
          make && make install
      RUN rm -rf /${FILENAME}}
      CMD ["nginx", "-g", "daemon off;"]
      # ENTRYPOINT [ "rmbyext" ]
      • ENVARG:
        • ARG用于设置构建时的临时变量
        • ENV用于设置运行时的环境变量(但构建时也可以使用)
      • COPYADD:
        • COPY: 只能拷贝本地文件
        • ADD: 除了处理本地文件,还可以用于下载网络文件【不推荐使用,因为会创建更多的镜像层,且语义不明确】
      • CMDENTRYPOINT:
        • 如果ENTRYPOINT使用了shell模式,CMD指令会被忽略。
        • 如果ENTRYPOINT使用了exec模式,CMD指定的内容被追加为ENTRYPOINT指定命令的参数。
        • 如果ENTRYPOINT使用了exec模式,CMD也应该使用exec模式。
    • 多阶段构建
      # 第一阶段: 构建应用程序
      FROM node as builder
      WORKDIR /app
      COPY . .
      RUN npm install
      RUN npm run build
      # 第二阶段: 生成最终镜像
      FROM nginx:latest
      COPY --from=builder /app/build /usr/share/nginx/html
      EXPOSE 80
      CMD ["nginx", "-g", "daemon off;"]
  • 执行构建命令
    docker build -t imageName:imageTag .
  • 展示镜像分层
    docker image history <repository>:<tag>
    • 镜像由许多只读层组成,每个层都记录了由某些指令触发的一组新的状态更改
    • 当使用镜像启动容器时,会在其他层之上获得一个新的可写层

容器编排

  • 编写编排文件
    version: '3.8'
    networks:
      my_network:
        driver: bridge
    volumes:
      web_app_data: null
      database_data: null
    services:
      web_app:
        image: nginx:latest
        container_name: my_web_app
        ports:
          - "8080:80"
        volumes:
          - web_app_data:/usr/share/nginx/html
      database:
        image: mysql:latest
        container_name: my_database
        environment:
          MYSQL_ROOT_PASSWORD: mysecretpassword
          MYSQL_DATABASE: mydatabase
          MYSQL_USER: myuser
          MYSQL_PASSWORD: mypassword
        ports:
          - "3306:3306"
        volumes:
          - database_data:/var/lib/mysql
    • restart:
      • no: 不重启(默认设置)
      • on-failure[:x]: 如果非正常退出(不包含因docker daemon关闭的退出),则重启
      • always: 只要退出就重启
      • unless-stopped: 除非手动退出,不然就会重启
  • 相关操作
    • 展示服务
      docker-compose ps
    • 创建并运行
      docker-compose [--file docker-compose.yaml] up [--detach] [--build]
    • 执行命令
      docker-compose exec <service name> <command>
    • 停止与删除
      docker-compose down [--volumes]

容器网络

  • 网络模式
    • Host: 容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口【相当于Vmware中的桥接模式】
    • Bridge: 此模式会为每一个容器分配、设置IP等,并将容器连接到一个dockerO虚拟网桥,通过dockerO网桥以及iptables nat表配置与宿主机通信【相当于Vmware中的Nat模式】
    • None: 该模式关闭了容器的网络功能
    • Container: 创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围
    • Overlay: 用于跨多个Docker守护进程创建一个分布式网络,可以让容器实现跨主机通信【更多通过k8s实现】
    • Macvlan: 为容器分配一个独立的MAC地址,适用于需要直接与物理网络通信的场景【配置复杂,主要用于集成遗留系统】
  • 配置网络
    • 使用docker run启动容器时,用--network=--net=选项指定:
      • host模式: 使用--net=host指定
      • none模式: 使用--net=none指定
      • bridge模式: 使用--net=bridge指定,默认设置
      • container模式: 使用--net=container:NAME_or_ID指定
    • 使用docker-compose创建容器:
      version: '3.8'
      services:
        web:
          image: nginx
          networks:
            - my_network
        db:
          image: mysql
          network_mode: "host"
      networks:
        my_network:
编写
预览