Docker User Guide

Docker 简明用户指引

简介

使用 Docker 容器,除了安装 Docker 环境,还需要准备镜像文件。镜像文件默认基于 Alphine Linux 构建。

镜像文件由不同的只读文件系统层构成。同一镜像可以创建不同的容器,每个容器有同属镜像的只读层,还有各自的读写层,读写层会随着容器一起删除。

需要读写的文件推荐放在宿主机,通过卷(Volumn)挂载进入容器,删除容器不会影响宿主机上的文件。

应用场景

  • 解决环境版本冲突。

下载

参考

常用路径 作用
/var/run/docker.sock Linux/macOS 本地侦听路径
/etc/containers/registries.conf CentOS 8 镜像仓库配置文件
~/Library/Group\ Containers/group.com.docker/settings.json macOS 配置文件
\\.\pipe\docker_engine Windows 本地侦听路径

配置

Linux 开启远程管理

新建或编辑 /etc/systemd/system/docker.service.d/override.conf 文件,重置 ExecStart 指令,添加 2375 端口侦听后重启服务:

[Service]
ExecStart=
ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2375 --containerd=/run/containerd/containerd.sock
sudo systemctl daemon-reload
sudo systemctl restart docker.service

macOS 开启远程管理

可通过 socat 转发 Unix Socks 实现:

brew install socat
sudo socat TCP-LISTEN:2375,reuseaddr,fork UNIX-CONNECT:/var/run/docker.sock

Windows/macOS 管理远程 Docker

设置环境变量或自定义 .bat 文件可远程管理 docker 服务,macOS 参考这里

$env:DOCKER_HOST="tcp://IP_OR_HOSTNAME:2375"
REM docker.bat
@docker -H=IP_OR_HOSTNAME:2375 %*

服务端代理

mkdir -p /etc/systemd/system/docker.service.d

# /etc/systemd/system/docker.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=http://proxy.example.com:80"
Environment="HTTPS_PROXY=https://proxy.example.com:443"
Environment="NO_PROXY=localhost,127.0.0.1,docker-registry.example.com,.corp"


# Restart & Verify
sudo systemctl daemon-reload
sudo systemctl restart docker
sudo systemctl show --property=Environment docker

客户端代理

用户主要使用 docker 命令行和 docker 服务进行交互。国内拉取镜像过慢,或启动的容器需要传入代理时可在客户端配置文件 ~/.docker/config.json 中添加代理设置:

  "proxies":
  {
    "default":
    {
      "httpProxy": "http://192.168.1.111:8118",
      "httpsProxy": "http://192.168.1.111:8118",
      "noProxy": "localhost,mirror.aliyuncs.com,*.mirror.aliyuncs.com,*.163.com,*.aliyuncs.com"
    }
  },

镜像加速器

Docker 服务端可配置镜像加速器,加快镜像获取,设置 Docker Engine:

  "registry-mirrors": [
    "https://hub-mirror.c.163.com"
  ],

自动补全

Docker for Mac

# .zshrc
etc=/Applications/Docker.app/Contents/Resources/etc
ln -s $etc/docker.zsh-completion /usr/local/share/zsh/site-functions/_docker
ln -s $etc/docker-compose.zsh-completion /usr/local/share/zsh/site-functions/_docker-compose

fpath=(/usr/local/share/zsh/site-functions $fpath)
autoload -Uz compinit && compinit -u
# .bashrc

常用命令

Docker 管理

命令 作用
docker stats 容器运行仪表板

巡查 Docker for Mac 虚机

# Ctrl + a, d 可挂起 screen,Ctrl + a, k 可关闭 screen
screen ~/Library/Containers/com.docker.docker/Data/vms/0/tty
# 2.4.0.3+
docker run -it --privileged --pid=host debian nsenter -t 1 -m -u -n -i sh

环境管理

命令 作用
docker info 确认 Docker 及相关系统层面状态
docker version 确认客户端及服务器版本
docker --version 确认客户端版本
docker-compose --version
docker-machine --version
docker image prune -f 清理无标签镜像
docker container prune -f 清理已停止容器
docker volume prune -f 清理无用卷
docker system prune -f 清理无用镜像、网络
docker builder prune -a 清理镜像构建缓存

镜像管理

镜像本质是个 tar 包,用作容器模版。编译镜像时,当前目录内容打包成 tar 文件后发送至 dockerd 进程。未显式指明标签时,docker 命令默认引用 latest 标签。镜像完整标识 REGISTER_URL/USER/IMAGE:TAG。

# 更新所有本地镜像已安装版本对应的最新版。
docker images | grep -v REPOSITORY | awk '{print $1":"$2}' | xargs -L1 docker pull # Linux / Mac

# 清理升级后无用的历史镜像
docker rmi $(docker images -q -f dangling=true)
命令 作用
docker images 列出所有本地镜像
docker image ls 列出所有本地镜像
docker search KEYWORD 搜索镜像
docker [image] history [USER/]IMAGE[:TAG] 巡查镜像构建步骤
docker history --no-trunc --format {{.CreatedBy}} [USER/]IMAGE[:TAG] 显示完整步骤
docker build -t [USER/]IMAGE[:TAG] . 在当前目录编译 Dockerfile 生成镜像
docker image rm [USER/]IMAGE[:TAG] 删除镜像
docker rmi [USER/]IMAGE[:TAG] 删除镜像
docker pull [USER/]IMAGE[:TAG] 从 Docker 仓库下载镜像
docker image save -o TAR_FILE [USER/]IMAGE[:TAG] 导出镜像
docker image load -i TAR_FILE 导入镜像
docker [image] tag LOCAL_IMAGE:TAG [USER/]IMAGE[:TAG] 发布准备:给镜像打标签

容器管理

命令中的 CONTAINER 可以是容器名,亦或是容器 ID。除了 ls 指令,其他命令中的 container 关键字可以省略。

开关 作用
--cpu 限制 CPU 使用率
--memory 限制内存使用率
--read-only 限制磁盘写入
命令 作用
docker container ls 列出运行中的容器
docker ps 列出运行中的容器
docker container ls -a 列出所有容器
docker ps -a 列出所有容器
docker container run --name CONTAINER IMAGE CMD
docker container rm -fv CONTAINER 强制删除容器及相关卷
docker container rm -f $(docker container ls -aq) 根据容器 ID 删除所有容器
docker container stop CONTAINER 停止容器
docker container start CONTAINER 启动容器
docker container restart CONTAINER 重启容器
docker container top CONTAINER 查看容器内的进程
docker container inspect CONTAINER 巡查容器,如:卷 Volume 映射到宿主机的路径
docker container exec -it CONTAINER COMMAND 通过 TTY 终端和容器交互,Ctrl + d / exit 退出容器
docker container attach CONTAINER 进入容器查看主进程输出,Ctrl + p 跟 Ctrl + q 退出容器
docker container logs --tail 10 -f CONTAINER tail 容器标准输出
docker container port CONTAINER 容器端口映射详情
docker cp CONTAINER:PATH HOST_PATH 复制文件到宿主机
docker cp HOST_PATH CONTAINER:PATH 复制文件到容器
docker container diff CONTAINER 相比镜像发生的变化
docker container commit CONTAINER IMAGE 保存容器为镜像

卷管理

卷比容器生命周期更长,用于存储容器状态。

命令 作用
docker volume create VOLUME 创建卷
docker volume inspect VOLUME 巡查卷
docker volume rm VOLUME 删除卷
docker volume rm $(docker volume ls -q) 删除所有未挂载卷

网络管理

Docker 服务端默认创建虚拟网卡 docker0,构建 Docker 默认网络:bridge。容器内可以通过宿主机 IP 连接宿主机,不同 Docker 网络的容器无法通信。容器的网络端口可以由宿主机端口映射,该映射只能在容器创建····时指定。

命令 作用
docker network ls 查看现有网络
docker network inspect bridge 查看 Bridge 详情
docker network create [--driver bridge] [--subnet CIDR] NETWORK 新建网络
docker network rm NETWORK 删除网络

Docker 网络在创建容器时通过 --network NETWORK 参数指定。可以指定新建的 Docker 网络,也可以用以下预定义 Docker 网络。--network 参数可以有多个。也可用 --network container:CONTAINER 接入指定容器网络。

预定义网络 作用
bridge 默认 Docker 网络,无 DNS 服务
host 使用宿主机网络
none 容器无 Docker 网络

https://stackoverflow.com/questions/24319662/from-inside-of-a-docker-container-how-do-i-connect-to-the-localhost-of-the-mach

在 Docker for Mac 的容器中可以用以下 hostname:

Hostname 作用
host.docker.internal 连接宿主机
gateway.docker.internal

容器注册表管理

命令 作用
docker login -u USER -p PASSWORD 登录容器注册表
docker push [USER/]IMAGE[:TAG] 发布镜像到容器注册表

Dockerfile

通过 Dockerfile 文件及 docker build 命令可编译自定义镜像。Dockerfile 关键字开始,关键字 FROM、COPY、RUN 开始的每一行对应镜像中的一层。

关键字

Dockerfile 关键字 作用
# COMMENT 注释
ARG IMAGE_VARIABLE=VALUE 声明镜像环境变量
$(IMAGE_VARIABLE) 引用镜像环境变量
FROM scratch 无父镜像
FROM IMAGE:TAG 引用父镜像
FROM IMAGE:TAG AS build 引用父镜像;声明多步镜像名
USER username 后续操作用户
RUN COMMAND && COMMAND 运行命令;可用 \ 跨行
COPY HOST_PATH CONTAINER_PATH 复制当前文件夹的内容
COPY --from=build BUILD_CONTAINER_PATH CONTAINER_PATH 复制多步镜像的内容
ADD HOST_TAR_PATH CONTAINER_PATH 添加并解压文件
ADD URL CONTAINER_PATH 从 URL 添加非当前文件夹的内容
VOLUME PATH, PATH 声明自建卷
WORKDIR CONTAINER_PATH 设置后续指令工作目录
ENV VARIABLE=VALUE 声明环境变量
EXPOSE PORT/PROTOCL 注释容器可侦听端口
ENTRYPOINT 随容器启动命令
CMD ENTRYPOINT 参数,容器启动时可覆盖

设置

# 输出 Build 详情
export DOCKER_BUILDKIT=0

命令

# 跳过 build 缓存
docker build --no-cache

Docker Compose

单机容器编排工具。默认读取当前目录中的配置文件 docker-compose.yml 及 docker-compose.override.yml 编译镜像、启动容器。

开关 作用
-f COMPOSE_FILENAME 指定非默认配置文件名
-p PROJECT 自定义 Compose 项目名称,默认为目录名
--scale SERVICE=NUM 指定服务对应的容器创建/启动个数
命令 作用
docker-compose build 编译当前目录中 docker-compose.yml 声明的镜像
docker-compose up [创建并]启动当前目录中 docker-compose.yml 声明的容器
docker-compose up -d 后台模式
docker-compose ps 列出通过 docker-compose 启动的容器
docker-compose down 关闭并删除当前目录中 docker-compose.yml 声明的容器
docker-compose down -v 删除容器时同时删除声明的卷
docker-compose push 推送编译的镜像

docker-compose.yml

关键字 意义
version: "2.4" "2.x" 单机版;"3.x" Docker Swam/Kubernetes 版
services: 服务声明开始
  SERVICE: 提供服务的容器声明开始
    image: [USER/]IMAGE[:TAG] 声明容器镜像
    build: PATH 镜像未就绪时,根据路径下的 Dockerfile 编译镜像
    volumes: 卷声明开始
      - HOST_PATH:CONTAINER_PATH
      - VOLUME:CONTAINER_PATH
    ports: 端口声明开始
      - HOST_PORT:CONTAINER_PORT
    environment:
      VARIABLE: VALUE 覆盖环境变量
volumes:
  VOLUME: 声明可写卷
build: 定义编译时相关参数
  context: SERVICE
  dockerfile: DOCKERFILE_NAME

安装

# Install the Compose standalone
# Linux
curl -SL https://github.com/docker/compose/releases/latest/download/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

常见用例

nginx + php:5-fpm

nginx 默认配置文件没有开启 FastCGI 支持及 PHP 集成,需要挂载自定义配置文件或自定义 nginx 镜像实现 LNMP 环境:

## nginx 配置文件: default.conf,覆盖镜像中的 /etc/nginx/conf.d/default.conf 文件
 # 想定代码放在 /var/www/html 目录中
 #
server {
    listen       80;
    server_name  localhost;

    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;

    location / {
        root   /var/www/html;
        index  index.html index.htm;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /var/www/html;
    }

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    location ~ \.php$ {
        proxy_set_header X-Real-Ip $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_set_header REMOTE_ADDR $remote_addr;

        root           /var/www/html;
        fastcgi_pass   php_5_fpm:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    location ~ /\.ht {
        deny  all;
    }
}

启动 php:5-fpm 容器:

# 启动基于最新 php:5-fpm 镜像的容器

# 停止并删除已有容器
docker stop php_5_fpm
docker rm -v php_5_fpm

# 挂载代码目录,启动容器,PHP 应用存放的路径,FastCGI 服务需要读取权限
docker run -d -v /var/www/html:/var/www/html --name php_5_fpm --restart=always php:5-fpm

# 进入容器巡查,用 exit 命令可以退出容器
docker exec -it php_5_fpm bash

启动 nginx 容器(基于自定义镜像): 

# 镜像定义文件 Dockerfile
FROM nginx:1.15
COPY conf/default.conf /etc/nginx/conf.d/default.conf
# 停止并删除既存容器、删除既存镜像
docker stop nginx_php_5_fpm
docker rm -v nginx_php_5_fpm
docker rmi nginx_php_5_fpm

# 生成自定义镜像
docker build . -t nginx_php_5_fpm

# 启动容器
docker run -d -it -p 60080:80 -v /var/www/html:/var/www/html --name nginx_php_5_fpm --link php_5_fpm:php_5_fpm --restart=always nginx_php_5_fpm

# 查看容器内进程
docker top nginx_php_5_fpm -ef

# 进入容器巡查,用 exit 命令可以退出容器
docker exec -it nginx_php_5_fpm bash

启动 nginx 容器(基于官方镜像),需要部署自定义 nginx 配置文件,以下想定部署位置为 /var/www/conf/default.conf。

# 停止并删除既存容器、删除既存镜像
docker stop nginx_php_5_fpm
docker rm -v nginx_php_5_fpm


# 启动容器
docker run -d -it -p 60080:80 -v /var/www/conf/default.conf:/etc/nginx/conf.d/default.conf -v /var/www/html:/var/www/html --name nginx_php_5_fpm --link php_5_fpm:php_5_fpm --restart=always nginx:1.15

# 查看容器内进程
docker top nginx_php_5_fpm -ef

# 进入容器巡查,用 exit 命令可以退出容器
docker exec -it nginx_php_5_fpm bash

自定义 nginx 镜像

# 镜像定义文件 Dockerfile
FROM nginx:1.14.0
COPY conf/<site-domain>.conf /etc/nginx/conf.d/
COPY ~/nginx/headers-more-nginx-module/nginx-module-headersmore_1.14.0-1~xenial_amd64.deb /tmp
COPY ~/nginx/nginx-http-shibboleth/nginx-module-shibboleth_1.14.0-1~xenial_amd64.deb /tmp
RUN dpkg -i /tmp/nginx-module-headersmore_1.14.0-1~xenial_amd64.deb /tmp/nginx-module-shibboleth-dbg_1.14.0-1~xenial_amd64.deb

官方 nginx 镜像 + 宿主机 PHP

利用 nginx 官方镜像,可以让不同版本的 nginx 服务同时运行,并访问宿主机上的其他服务,具体方法如下:

按需准备 nginx.conf,Ubuntu 需要把 nginx 运行在 www-data 用户下:

# Ubuntu 版 nginx.conf,user 改为 www-data,否则访问 PHP Unix socket 有权限问题。
user  www-data;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  300;

    gzip  on;

    client_max_body_size 64m;

    include /etc/nginx/conf.d/*.conf;
}

准备应用配置文件,不同的应用,所需配置稍有不同:

# Drupal 应用配置(无 HTTPS)
server {
    listen 80;
    listen [::]:80;

    root        <Application Root Path>;
    server_name <domain name>;

    index index.php index.html;

    # 屏蔽容易泄漏系统信息的文件
    location ~* ^/(readme\.txt|CHANGELOG\.txt|web\.config|robots\.txt|LICENSE\.txt|README.mk) {
        return 404;
        #deny all;
    }

    location ~* \.(eot|ttf|woff|otf)$ {
        add_header Access-Control-Allow-Origin *;
    }

    location / {
        try_files $uri /index.php?$query_string;
        # 屏蔽沙俄黑客 IP
        deny 180.97.0.0/16; 
    }

    location @rewrite {
        rewrite ^/(.*)$ /index.php?q=$1;
    }

    location ~ \.php$ {
        fastcgi_pass   unix:/run/php/php7.0-fpm.sock;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }

    error_log   /var/log/nginx/<domain name>-error.log warn;
    access_log  /var/log/nginx/<domain name>-access.log  main;

    fastcgi_read_timeout 300s;
}

容器更新、启动命令: 

# 停止并删除既存容器
docker stop nginx_local_php_fpm
docker rm nginx_local_php_fpm

# 挂载宿主机 Socket 文件,nginx 配置文件
export PHP_APPLICATION=$(pwd)
export NGINX_MODULE_PATH=$(pwd)
docker run -d -p 60601:80 -v /run/php/php7.0-fpm.sock:/run/php/php7.0-fpm.sock -v $PHP_APPLICATION/docs:$PHP_APPLICATION/docs -v $NGINX_MODULE_PATH/nginx-http-shibboleth/usr/lib/nginx/modules/ngx_http_shibboleth_module.so:/usr/lib/nginx/modules/ngx_http_shibboleth_module.so -v $NGINX_MODULE_PATH/headers-more-nginx-module/usr/lib/nginx/modules/ngx_http_headers_more_filter_module.so:/usr/lib/nginx/modules/ngx_http_headers_more_filter_module.so -v $PHP_APPLICATION/logs/:/var/log/nginx/ -v $PHP_APPLICATION/conf/nginx.conf:/etc/nginx/nginx.conf -v $PHP_APPLICATION/conf/site.conf:/etc/nginx/conf.d/site.conf --name nginx_local_php_fpm --restart=always nginx:1.14.0

Author: njun
njun's picture
Updated: 2023/04/04