Docker

 

Docker 参考文档

Docker 命令行文档

安装及升级 docker

RedHat/CentOS

安装仓库文件

sudo yum install -y yum-utils

sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

安装 docker

sudo yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin

升级 docker 版本

sudo yum update 'docker-ce*'

docker system

管理 docker 系统

# 检查 docker 占用的系统空间
docker system df

# 显示 docker 系统信息
docker system info

# 删除无用的容器,网络,镜像等
docker system prune

docker build

docker build -t image-name:tag /image/context/path

# 生成镜像到指定registry
docker build -t registry-host:port/image-name:tag /image/context/path

# 引用其它image:tag生成一个新image:tag
docker tag <source-image>[:tag] <new-image>[:tag]

docker image

docker images

docker images

# 列出所有无标签的镜像 (dangling)
docker images --filter 'dangling=true'

# 列出镜像名包含指定模式的镜像,例如镜像名为 'www.myregistry.net/app/web-service:1.0.3'
docker images --filter 'reference=*/*/web*'
docker images --filter 'reference=www.myregistry.net/*/*'

可以同时使用多个 --filter 参数进行筛选

docker image rm

docker rmi image-name

# 删除所有无标签(dangling)镜像
docker rmi $(docker images --filter 'dangling=true' -q)

docker image prune

# 删除所有无标签(dangling)镜像
docker image prune

# 删除所有无标签和不被任何容器引用的镜像
docker image prune -a

docker history

查看镜像的生成历史,层信息等

docker history image-name

docker login

docker login registry-url

docker pull registry-host:port/image-name:tag
docker push registry-host:port/image-name:tag

docker container

Docker run 命令参考

# 查看当前运行的容器
docker ps [-a]

# 运行容器, --rm 允许容器退出时自动删除该容器
docker run -it --rm [--name <container-name>] [-v <host-dir:container-dir>] [-p <host-port:container-port>] <image-name> [command]

# 后台运行容器
docker run -d --rm [--name <container-name>] <image-name> [command]

# 在指定容器内运行命令
docker exec <container-name> ls -l

# 以可交互方式进入容器
docker exec -it <container-name> bash

# 容器重命名
docker rename <container-name> <new-name>

# 停止所有正在运行的容器
docker stop $(docker ps -q)

# 删除所有停止的容器
docker rm $(docker ps --filter 'status=exited' -q)

# 删除指定名称的容器
docker rm $(docker ps --filter 'name=substr' -q)

# 删除所有镜像
docker rmi `docker images -q`

docker save & load

# 从容器生成镜像
docker commit <container-name> <image-name:tag>

# 将一或多个镜像保存到tar文件
docker save -o image.tar <image-name:tag>

# 从保存的tar文件恢复镜像
docker load -i image.tar

# 从容器中导出文件系统
docker export -o container-fs.tar <container-name>

# 将文件系统导入镜像中
docker import container-fs.tar <image-name:tag>

docker logs

# Follow log output
docker logs <container_name> -f

# Show timestamps
docker logs <container_name> -t

# Number of lines to show from the end of the logs
docker logs <container_name> --tail 10

# Show logs since timestamp (e.g. 2022-05-05T12:30:00Z) or relative (e.g. 1h30m for 1 hour and 30 minutes)
docker logs <container_name> --since 1h30m
docker logs <container_name> --since 2022-05-05T12:30:00Z

# Use multiple options
docker logs <container_name> -t -f --tail 50

Prune unused Docker objects

  • 清理 image 对象的无用数据
# Only cleans up dangling images. A dangling image is one that is not tagged
# and is not referenced by any container.
docker image prune

# To remove all images which are not used by existing containers
docker image prune -a

# Only remove images created more than 24 hours ago
docker image prune -a --filter "until=24h"
  • 清理 container 对象的无用数据
# To remove stopped containers older that 24 hours
docker container prune -a --filter "until=24h"
  • 清理 volume 对象的无用数据
# To remove volumes which are not labeled with the "keep" label
docker volume prune -a --filter "label!=keep"
  • 清理 network 对象的无用数据
docker volume prune -a --filter "until=24h"
  • 清理多种对象的无用数据
# This is a shortcut that prunes images, containers, and networks. Volumes are not pruned by default
docker system prune

# To also prune volumes
docker system prune --volumes

在 Container 中访问外部 Docker Daemon

以 Alpine 镜像为例,假设宿主机 Docker daemon 的套接字文件是 /var/run/docker.sock

docker run -it \
           --rm \
           --name alpine \
           -e http_proxy=http://127.0.0.1:7890 \
           -e https_proxy=http://127.0.0.1:7890 \
           -v /var/run/docker.sock:/var/run/docker.sock \
           alpine

apk add --no-cache docker-cli

Dockerfile

docker build 命令从 Dockerfilecontext 构建镜像。构建使用的上下文是包含一组文件的 PATHURLPATH 是本地文件系统上的目录,URL 是一个 Git 仓库位置。

构建上下文会递归处理文件。所以 PATH 会包含所有子目录,URL 会包含所有 submodules。下面例子的构建命令使用当前目录 (.) 作为构建上下文。

docker build .

Dockerfile 通常位于上下文的根目录中,但可以在 docker build 中使用 -f 标志来指向文件系统中任何位置的 Dockerfile。

docker build -f /path/to/a/Dockerfile .

也可以指定要生成镜像的 repository 和 tag

docker build -t shykes/myapp .

使用多个 -t 参数可以给镜像打不同的 tag 并生成到多个 repository

docker build -t shykes/myapp:1.0.2 -t shykes/myapp:latest .

SpringBoot Java App Dockerfile

FROM maven:3.8.6-openjdk-11-slim AS builder
LABEL maintainer="appuser@exmaple.com"

ARG MAVEN_OPTS

RUN mkdir /build
WORKDIR /build
COPY pom.xml $HOME
RUN mvn verify --fail-never
COPY . /build
RUN mvn clean package -DskipTests

FROM adoptopenjdk/openjdk11:alpine-jre
LABEL maintainer="appuser@exmaple.com"

ARG BUILD_DATE
ARG BUILD_VERSION
ARG VCS_REF

LABEL org.label-schema.schema-version="1.0"
LABEL org.label-schema.build-date=$BUILD_DATE
LABEL org.label-schema.name="java-app"
LABEL org.label-schema.version=$BUILD_VERSION
LABEL org.label-schema.description="java app for test purpose."
LABEL org.label-schema.url="https://java-app.example.com"
LABEL org.label-schema.vcs-url="https://github.com/example/java-app.git"
LABEL org.label-schema.vcs-ref=$VCS_REF
LABEL org.label-schema.docker.cmd="docker run -d -e SPRING_PROFILES_ACTIVE=test -p 8900:8900 java-app"

RUN apk add --no-cache tini
RUN addgroup -S appuser && adduser -S -s /bin/false -G appuser appuser
RUN mkdir /app
WORKDIR /app
RUN chown -R appuser:appuser /app
COPY --chown=appuser:appuser --from=builder /build/target/java-app.jar /app
USER appuser

EXPOSE 8900
ENTRYPOINT ["tini --"]
CMD ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "java-app.jar"]
  • 第一阶段构建时,Maven 需要通过代理下载依赖,可以设置 MAVEN_OPTS 环境变量 来向启动 Maven 的 JVM 传递代理设置。
  • 第二阶段构建时,apk 需要通过代理下载 tini 工具,可以设置 http_proxyhttps_proxy 环境变量来使用代理,因为这两个环境变量是 Dockerfile 的预定义 ARGs,所以不需要在 Dockerfile 中再使用 ARG http_proxyARG https_proxy

使用 Dockerfile 构建镜像,并使用 --build-arg 参数传递 ARG 环境变量

docker build --rm \
             --build-arg BUILD_DATE=$(date -u -Is) \
             --build-arg BUILD_VERSION=1.0.0 \
             --build-arg VCS_REF=$(git rev-parse HEAD) \
             --build-arg http_proxy=http://127.0.0.1:7890 \
             --build-arg https_proxy=http://127.0.0.1:7890 \
             --build-arg MAVEN_OPTS="-Dhttp.proxyHost=127.0.0.1 -Dhttp.proxyPort=7890 -Dhttps.proxyHost=127.0.0.1 -Dhttps.proxyPort=7890" \
             -t java-app .

启动 SpringBoot app 容器

docker run -it --name app-name -e SPRING_PROFILES_ACTIVE=test -p 8900:8900 java-app

docker-compose

安装 docker-compose

sudo curl -L "https://github.com/docker/compose/releases/download/1.24.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

docker-compose 命令行

docker-compose 命令

docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...]

Options:
  -f, --file FILE             Specify an alternate compose file
                              (default: docker-compose.yml)
  -p, --project-name NAME     Specify an alternate project name
                              (default: directory name)
  --project-directory PATH    Specify an alternate working directory
                              (default: the path of the Compose file)

Commands:
  build              Build or rebuild services
  bundle             Generate a Docker bundle from the Compose file
  config             Validate and view the Compose file
  create             Create services (deprecated)
  down               Stop and remove containers, networks, images, and volumes
  events             Receive real time events from containers
  exec               Execute a command in a running container
  help               Get help on a command
  images             List images
  kill               Kill containers
  logs               View output from containers
  pause              Pause services
  port               Print the public port for a port binding
  ps                 List containers
  pull               Pull service images
  push               Push service images
  restart            Restart services
  rm                 Remove stopped containers
  run                Run a one-off command
  scale              Set number of containers for a service
  start              Start services
  stop               Stop services
  top                Display the running processes
  unpause            Unpause services
  up                 Create and start containers
  version            Show the Docker-Compose version information

如果没有通过-f指定docker-compose.yml文件路径,Compose会搜索当前目录及其父目录来寻找docker-compose.yml.

# 启动服务,-d 选项让服务后台运行(detach)
docker-compose up -d [SERVICE...]

# 停止容器并删除up命令创建的容器,网络
docker-compose down

# 列出容器
docker-compose ps [SERVICE...]

# 列出服务名
docker-compose ps --services

# 列出服务创建容器时要使用的镜像
docker-compose images [SERVICE...]

# 显示正在运行的进程
docker-compose top

# 构建或重新构建服务,默认镜像名为 project_service 格式,比如 test_db
docker-compose build [SERVICE...]

# 拉取在 Compose file 中定义的服务镜像,但不启动容器
docker-compose pull [SERVICE...]

# 推送服务镜像
docker-compose push [SERVICE...]

Compose file 示例

docker-compose.yml

version: '3.7'
services:
  db:
    image: postgres:14.3
    container_name: postgresql
    restart: on-failure
    environment:
      POSTGRES_PASSWORD: postgres
    ports:
      - 5432:5432
    volumes:
      - /var/postgres_data:/var/lib/postgresql/data
    networks:
      - devops

  pgadmin:
    image: dpage/pgadmin4
    container_name: pgadmin4
    restart: on-failure
    environment:
      PGADMIN_DEFAULT_EMAIL: admin@example.com
      PGADMIN_DEFAULT_PASSWORD: admin-password
    ports:
      - 5050:80
    volumes:
      - /var/pgadmin_data:/var/lib/pgadmin
    networks:
      - devops

  jenkins:
    image: jenkins/jenkins:lts-jdk11
    container_name: jenkins
    restart: on-failure
    environment:
      JENKINS_OPTS: --prefix=/jenkins
      JAVA_OPTS: -Dhttp.proxyHost=127.0.0.1 -Dhttp.proxyPort=7890 -Dhttps.proxyHost=127.0.0.1 -Dhttps.proxyPort=7890
    ports:
      - 8080:8080
      - 50000:50000
    volumes:
      - /var/jenkins_home:/var/jenkins_home
    networks:
      - devops
  
  jenkins-inbound-agent:
    image: jenkins/inbound-agent
    container_name: jenkins-inbound-agent
    depends_on:
      - jenkins
    init: true
    restart: on-failure
    environment:
      JENKINS_URL: "http://jenkins:8080/jenkins"
      JENKINS_SECRET: "32ef99b39f55e1e3d4d717d5ae4db42384b09fb5acc524bf795f0e72f46ba9c8"
      JENKINS_AGENT_NAME: "Agent"
      JENKINS_AGENT_WORKDIR: "/home/jenkins/agent"
    networks:
      - devops

  nginx:
    image: nginx:1.21.6
    container_name: nginx
    restart: on-failure
    ports:
      - 8088:80
      - 8443:443
    volumes:
      # sudo chown 101.101 /var/nginx_conf
      - /var/nginx_conf:/etc/nginx/
    networks:
      - devops

  nexus:
    image: sonatype/nexus3:3.39.0
    container_name: nexus3
    restart: on-failure
    ports:
      - 8081:8081
    volumes:
      - nexus-data:/nexus-data
    networks:
      - vpc

# 创建自定义网络,如果不使用 name 属性指定网络名,所创建的网络名称是 "当前目录名_网络名"
networks:
  vpc:
    name: devops

有些选项需要特定版本支持,比如 init 选项只在 compose file 3.7 版本后才可用,此时需要指定 version: "3.7"。可以查看官网的 Compatibility matrix 来了解可用的 compose file 版本以及对应的 docker 版本要求。

为 Docker Daemon 设置代理

Docker的三种网络代理配置

Dockerd 代理

在执行 docker pull 时,是由守护进程 dockerd 来执行。因此,代理需要配在 dockerd 的环境中。

如果是直接启动 dockerd,则在命令前直接加入环境变量

HTTP_PROXY=http://127.0.0.1:8080 HTTPS_PROXY=http://127.0.0.1:8080 dockerd

如果是 systemd 启动的系统,可以在 systemd 的 docker 服务中配置这环境变量。

sudo mkdir -p /etc/systemd/system/docker.service.d
sudo vim /etc/systemd/system/docker.service.d/proxy.conf
[Service]
Environment="HTTP_PROXY=http://127.0.0.1:8080/"
Environment="HTTPS_PROXY=http://127.0.0.1:8080/"
Environment="NO_PROXY=localhost,127.0.0.1,.example.com"

修改后通过 systemctl 命令重新加载配置并重启 docker 使代理生效

sudo systemctl daemon-reload
sudo systemctl restart docker

参考官方文档 Control Docker with systemd

Container 代理

在容器运行阶段,如果需要代理上网,则需要配置 ~/.docker/config.json 文件。 以下配置,只在Docker 17.07及以上版本生效。

{
 "proxies":
 {
   "default":
   {
     "httpProxy": "http://127.0.0.1:7890",
     "httpsProxy": "http://127.0.0.1:7890",
     "noProxy": "*.test.example.com,.example2.com,127.0.0.0/8"
   }
 }
}

这个是用户级的配置,除了 proxiesdocker login 等相关信息也会在其中。 而且还可以配置信息展示的格式、插件参数等。

此外,容器的网络代理,也可以直接在其运行时通过 -e--env 注入 http_proxy 等环境变量。这两种方法分别适合不同场景。config.json 非常方便,默认在所有配置修改后启动的容器生效,适合个人开发环境。在 CI/CD 的自动构建环境、或者实际上线运行的环境中,这种方法就不太合适,用 -e 注入这种显式配置会更好,减轻对构建、部署环境的依赖。当然,在这些环境中,最好用良好的设计避免配置代理上网。

代理配置后会立即生效。

官方文档 Configure Docker to use a proxy server

Docker Build 代理

虽然 docker build 的本质,也是启动一个容器,但是环境会略有不同,用户级配置无效。在构建时,需要注入 http_proxy 等参数。

docker build . \
    --build-arg "HTTP_PROXY=http://127.0.0.1:7890/" \
    --build-arg "HTTPS_PROXY=http://127.0.0.1:7890/" \
    --build-arg "NO_PROXY=localhost,127.0.0.1,.example.com" \
    -t your/image:tag

执行时代理立即生效

Escape Sequence

使用 escape sequence 在容器内退出容器而不停止容器。注意:容器必须以 docker run -it 选项启动该按键序列才有效

CTRL-p CTRL-q
  • docker run -t -i → can be detached with CTRL-p CTRL-q; and reattached with docker attach
  • docker run -i → cannot be detached with CTRL-p CTRL-q; will disrupt stdin
  • docker run → cannot be detached with CTRL-p CTRL-q; can SIGKILL client; can reattach with docker attach

如果容器是以 docker-compose 启动,使用以下 escape sequence 退出容器而不停止容器

CTRL+\