写给女朋友的 Docker 教程,从安装到指令再到Dockerfile再到docker-compose,你想要的全都有!!!

314 阅读7分钟

本文与其说是教程不如说是手册,记录了大量的 api,建议手操一遍,有个印象,后面用到了再回来看看,建议阅读时间 10-30 分钟,手操时间:1-3 小时,还可以在我的官方网站 zhengshaoguo.com/blogs/22 学习哦

Docker 是一个用于开发,交付和运行应用程序的开放平台,能够将应用程序与基础架构分开,从而可以快速交付软件,大大减少编写代码和在生产环境中运行代码之间的延迟,Docker 可以包含多个容器,容器通过镜像创建,容器之间相互隔离,互不影响。

1.1 相关链接

1.2 安装和启动

1.2.1 安装 Docker

sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin

1.2.2 Docker 服务

systemctl start docker  # 启动
systemctl status docker  # 查看状态
systemctl reload docker  # 重启
systemctl stop docker  # 停止

1.3 Docker 指令

1.3.1 docker 权限

需要将普通用户加到 docker 组,赋予普通用户执行 docker 的权限

adduser dr -g docker

1.3.2 常用选项

docker -v  # 查看版本号
docker --help  # 查看所有命令
docker --config string  # 指定配置文件,默认为 /root/.docker

1.3.3 基础命令

docker info  # 显示系统的信息
docker version  # 查看版本

1.3.4 镜像命令

docker search string  # 搜索镜像
docker pull string:版本  # 下载镜像(docker hub)
docker images  # 查看所有已安装镜像
docker rmi id  # 删除一个镜像
docker history nginx  # 查看镜像更改历史记录

1.3.5 容器命令

docker run [options] id  # 从镜像创建一个容器
  -i 交互模式
  -t 分配一个终端
  -d 后台运行
  -v 宿主机目录(覆盖容器中文件)/数据卷名(复制容器中文件):容器中的目录 | 将容器中的目录映射到宿主机中
  -p 宿主机端口:容器端口 | 指定端口映射
  --name 指定容器名称
  --volume-from 容器  与另一个容器共享所有的数据卷
  --rm  容器停止后自动删除
  --net  指定网卡
  --env k=v | 指定环境变量 
  --restart=no(默认不重启)、always(永远重启)、on-failure:n(非正常退出重启 n 次)、unless-stopped(不考虑 Docker 启动前已停止的容器)
docker ps  # 查看正在运行的容器  -a 所有的容器
docker rm id/name  # 删除一个容器,-f 强制删除,-v 同时删除挂载卷
docker stats id/name  # 显示容器的运行状态 CPU 等信息
docker stop id/name  # 停止一个容器
docker kill id/name  # 杀死一个容器的进程
docker start id/name  # 启动一个容器
docker pause id/name  # 暂停一个容器
docker unpause id/name  # 恢复容器
docker restart id/name  # 重启一个容器
docker rename old new  # 重命名容器
docker logs id/name  # 查看容器日志 -f 动态更新
docker attach id/name  # 使某个后台容器进入前台
docker inspect id/name  # 查看容器的配置信息 JSON 格式
docker top id/name  # 查看一个容器的进程
docker port id/name  # 查看容器映射到宿主机的端口
docker exec -it nginx bash  # 在一个容器里执行命令, -it 进入容器终端
docker cp ./a.txt id/name:/tmp  # 宿主机和容器之间复制文件或目录,-a 复制权限属组,-L 创建链接
docker diff id/name  # 查看容器内的文件变动记录
docker create --name xx 镜像id   # 创建一个容器
docker update --name newname id/name  # 更新容器的配置信息

1.3.6 仓库命令

docker login  # 登录 dockerhub
docker logout  # 登出
docker tag 镜像:版本 用户名/仓库名:版本   # 镜像打标签,创建一个新的镜像
docker push 用户名/仓库名:版本  # 将本地镜像推送到远程仓库
docker commit -a 作者 -m 描述信息 -p 执行时容器暂停 容器ID 镜像:版本  # 从容器创建一个新镜像
docker build .  # 通过 Dockerfile 生成一个镜像 
  -t  指定镜像名和版本
  -f  指定 Dockerfile 文件所在目录
  --no-cache  不使用缓存

1.3.7 导入导出

docker export -o a.tar id/name  # 将容器内的所有文件打包导出
docker import a.tar id/name  # 导入 tar 包作为容器镜像
docker save 镜像id1 镜像id2 -o a.tar  # 将镜像打包成一个 tar 包
docker load -i a.tar  # 将 tar 包导入为镜像

1.3.8 管理命令

docker image prune/rm/ls/tag/...  # 管理镜像,prune 删除没有使用的镜像
docker plugin  # 管理 docker 插件
docker config  # 管理 docker 配置文件
docker system  # 查看系统和磁盘信息
docker container  # 管理容器
docker network  # 管理容器的网络
docker volume create --name www  # 创建数据卷,数据卷的位置为:/var/lib/docker/volumes
docker volume inspect www  # 查看数据卷的信息

1.3.9 网络命名

docker network ls  # 查看所有网络连接方式,默认为桥接模式 bridge
docker network create mynet  # 创建一个网卡,不同网卡的容器,网络不互通
docker network connect 网卡 容器  # 不同网卡的容器实现通信

1.4 Dockerfile 构建镜像

1.4.1 创建项目

git clone https://github.com/dockersamples/node-bulletin-board.git

1.4.2 Dockerfile

FROM node:current-slim  # 基础镜像

WORKDIR /usr/src/app    # 指定工作目录
COPY package.json .     # 复制 package.json 到工作目录 
RUN npm install         # 执行命令 npm install 

EXPOSE 8080             # 绑定端口 8080
CMD [ "npm", "start" ]  # 执行命令 npm start

COPY . .                # 复制所有文件 

Dockerfile 的完整指令说明如下

# .dockerignore 将忽略的文件在此文件内声明,避免打包进镜像
# 设置基础镜像,必须在第一行指定
FROM centos:7

# 设置环境变量,可被后续的指令通过 $\{} 使用
ENV name zsg
ENV name=zsg age=18

# 给镜像添加标签,通过 docker inspect 可以查看这些信息
LABEL lang="python" version="9"

# 在构建镜像时执行命令,可通过 ; 分隔多条命令
RUN echo $\{name}
RUN ["ls", "-l"]

# 在容器运行时执行的命令,CMD 在 Dockerfile 文件中只有一条生效,重复使用会覆盖。
CMD echo $\{name}
CMD ["ls", "-l"]

# 在容器运行时执行命令,与 CMD 类似,此时 CMD 将作为它的参数
ENTRYPOINT ["ls", "-l"]

# 复制上下文中的文件到镜像中的任意位置,可设置用户和属组,源文件可以是 URL 地址
# 源文件是目录会复制目录下的所有文件到源地址,复制的是 tar 包将会自动解压
ADD n1.txt /var/
ADD --chown=root:bin n1.txt /var/

# 复制文件,与 ADD 类似
COPY n1.txt /var/

# 创建用于磁盘挂载的目录,挂载卷之后的修改不会保存
VOLUME ["/test"]

# 容器运行监听的端口,默认为 tcp
EXPOSE 85/tcp
EXPOSE 86/udp

# 指定容器中的用户
RUN useradd test1
USER test1

# 指定容器中工作目录
WORKDIR /workdir

1.4.3 生成镜像

docker build -t n1 .  #  生成镜像 n1

1.4.4 上传至镜像仓库

docker tag n1 a2440886651/test  # 重命名镜像
docker push a2440886651/test  # 推送到镜像仓库

1.5 构建 Nginx 镜像

1.5.1 Dockerfile

FROM centos:7

WORKDIR /workdir/

COPY nginx-1.23.3.tar.gz /workdir/nginx/

RUN cd nginx \
&& tar -xzf nginx-1.23.3.tar.gz \
&& yum install gcc pcre pcre-devel zlib-devel make -y \
&& cd nginx-1.23.3 \
&& ./configure --prefix=/workdir/nginx/app \
&& make \
&& make install

EXPOSE 80/tcp

CMD ./nginx/app/sbin/nginx -g  "daemon off;"

1.5.2 生成镜像

docker build -t n1 .

1.5.3 运行镜像

docker run -it --name n1 -p 82:80 -v /root/html:/workdir/nginx/app/html --rm n1

1.6 搭建私有仓库

常见的私有仓库技术有 Nexus、ArtiFactory,专业的 Docker 私有仓库有 Registry、Harbor

1.6.1 Registry 仓库

docker pull registry  # 安装镜像
docker run -d -p 5000:5000 --name registry registry  # 启动
docker pull nginx  # 在本地制作或拉取一个镜像
docker image tag nginx localhost:5000/mynginx  # 修改 Tag
docker push localhost:5000/mynginx  # 推送到 Registry
docker pull localhost:5000/mynginx  # 从 Registry 拉取
和 Registry 服务在同一台电脑可以使用 localhost:端口,在其他电脑上通过 IP:端口,当出现错误 http: server gave HTTP response to HTTPS client,修改 docker 配置文件即可

vi /etc/docker/daemon.json
{
    "insecure-registries": ["172.30.76.31:5000"]
}
systemctl daemon-reload
systemctl restart docker

1.6.2 Harbor 仓库

安装 Harbor

wget https://github.com/goharbor/harbor/releases/download/v2.7.0-rc2/harbor-offline-installer-v2.7.0-rc2.tgz
tar -xzf harbor-offline-installer-v2.7.0-rc2.tgz
cd harbor-offline-installer-v2.7.0-rc2
vim harbor.yml  # 修改配置项,见下文
./install.sh  # 启动 Harbor 服务
github 下载太慢,可以使用代理 https://ghproxy.com/https://github.com/...,安装 Harbor 需要 docker-compose,新版本的 docker 自带,使用 docker compose,旧版本还需手动安装,使用 docker-compose

Harbor 配置文件为安装目录的 harbor.yml 文件,常见的配置项有

hostname: 主机名,IP 或者 域名
http:
  port: HTTP 访问的端口号,默认为 80
https:
  port: HTTPS 访问的端口号,默认为 443
  certificate: SSL 证书路径
  private_key: SSL 秘钥路径
harbor_admin_password: 系统管理员的初始密码默认为 admin / Harbor12345
database: 
  password: 本地数据库密码
  max_idle_conns: 最大空闲连接数,默认为 50,若未配置则为 2,若 <= 0 则不保留
  max_open_conns: 最大连接数,默认为 100,若未配置则为 0,  <= 0 则不限制
data_volume: 挂载卷的位置,默认为 /data

当修改了 harbor.yml 后,需要执行以下步骤方能生效

docker compose down -v 
./prepare
docker compose up -d

Harbor 登录推送和拉取操作

docker login -u admin -p Harbor12345 172.30.76.31:8081  # 认证
docker tag SOURCE_IMAGE[:TAG] 172.30.76.31:8081/library/REPOSITORY[:TAG]  # 标记镜像
docker push 172.30.76.31:8081/library/REPOSITORY[:TAG]  # 推送
docker pull 172.30.76.31:8081/library/nginx  # 拉取

1.7 Docker-Compose

通过 Docker-Compose 可实现 Docker 容器集群的快速编排,定义一组相关联的应用容器为一个项目

1.7.1 安装

新版本的 Docker 自带 Docker-Compose

docker compose version

之前版本需要手动安装,docker compose 通过 python 编写,可通过 pip 安装或 源码安装 直接下载即可

pip install docker-compose

1.7.2 选项命令

  • -f: 指定 Compose 模板文件,默认为当前目录下的 docker-compose.yml
  • -p:指定项目名称,默认将使用所在目录名称作为项目名
  • --help:查看帮助

1.7.3 常用命令

docker compose up  # 创建并启动服务,-d: 在后台运行
docker compose down  # 停止并删除服务,-v: 同时删除卷
docker compose create  # 为服务创建容器
docker compose start  # 启动已经停止的服务
docker compose stop  # 停止正在运行的服务,-t: 设置超时时间,默认 10s
docker compose restart  # 重启已创建的服务,-t: 设置超时时间,默认 10s
docker compose rm  # 删除已经停止的服务,-f: 强制删除,-v: 同时删除卷
docker compose pause  # 暂停服务
docker compose unpause  # 恢复暂停的服务
docker compose kill  # 通过进程停止服务,-s 9:发送的停止信号 
docker compose ps  # 列出项目中已经创建的所有容器
docker compose images  # 列出正在运行的项目中所有的镜像
docker compose ls  # 列出正在运行的所有服务
docker compose logs  # 显示日志信息,不同的容器会用颜色区分,-f: 实时日志
docker compose build  # 构建(重新构建)项目中的容器。
docker compose pull  # 拉取服务依赖的容器镜像
docker compose run web hostname -I  # 在指定服务(web)上执行命令(hostname -I),容器无需启动
docker compose exec web bash  # 在指定服务(web)上执行命令(bash),需要启动容器,-d: 在后台运行
docker compose config  # 验证并查看 docker-compose.yml 文件
docker compose port web 80  # 查看某个容器(web)的端口(80)映射到宿主机的端口
docker compose top  # 查看各个容器运行的进程情况

1.7.4 模板语法

Docker-Compose 模板文件是一个 YAML 格式的文件,以 .yml 为扩展名

name: zsg  # 服务名
version: '3'  # 版本号,可使用 [1、2、3]
services:  # 定义服务
  web:  # 自定义容器
    image: node  # 创建容器的镜像名或 ID,若在本地不存在,则尝试从服务器拉取
    command: pwd  # 覆盖容器启动后默认执行的命令 CMD
    entrypoint: hostname -I  # 覆盖容器启动后的命令 ENTRYPOINT
    container_name: app  # 自定义的容器名,容器名默认为:服务-容器-序号 (zsg-web-1)
    restart: always  # 设置容器的启动策略,参考 1.3.5 docker run
    depends_on:  # 定义启动依赖,启动该容器会先启动依赖的容器(db)
      - db
    ports:  # 端口映射,不指定将随机映射一个主机端口
      - "3000"
      - "8000:8000"
    extra_hosts:  # 添加 hosts 记录
      - "zsg.com:192.168.1.1"
    volumes:  # 挂载一个目录或者一个已存在的数据卷容器
      - /var/www  # 自动创建数据卷
      - data:/var/www  # 挂载到自定义的数据卷 data(zsg_data)
      - /opt/data:/var/www:ro  # 挂载到指定的目录,并且该目录为只读
    expose:  # 暴露端口,但不映射到宿主机,只允许能被连接的服务访问
      - 8081
      - 9090
    extends:  # 模板继承,继承其中的一个容器
        file: common.yml
        service: webapp
    external_links:  # 链接到外部容器,可直接使用 n1 访问,前提是处于同一网卡,不同网卡参考 1.3.9
      - n1
    labels:  # 为容器添加元数据,可通过 inspect 查看 "Labels" 信息
      name: zzzzzzzzzzzzzzzzzz
    links:  # 链接到其它服务中的容器,使用容器名(db)或别名(db_link)访问,不同网卡参考 1.3.9
      - db
      - db:db_link
    networks:  # 为容器设置自定义的网卡
      - nwks
    healthcheck:  # 运行健康状态监测
      test: [ "CMD","curl","-f","http://localhost:8882" ]  # 类似ping
      interval: 1m30s  # 多久进行一次心跳检测
      timeout: 10s  # 超时时间
      retries: 3  # 超时尝试次数,三次尝试仍然无法取得联系则视为容器与docker引擎脱离关系
  db:
    build: ./dir  # 指定 Dockerfile 文件所在目录,在 up 时通过 build 打包成镜像并构建容器
    build:  # 可自定义上下文目录和 Dockerfile 文件名
      context: /root/tmp/compose/node  # 上下文目录,可以是 git 仓库的 url
      dockerfile: Dockerfile  # Dockerfile 文件名
    volumes_from:  # 从另一个服务或容器挂载其数据卷
      - zsg  # 同一个服务可省略
        - web  # 容器名
    environment:  # 定义环境变量
      - name=aaa
      - age=18
    env_file: .env  # 指定环境变量的文件,若有多个文件可以用数组(-)的形式
    cap_add:  # 增加容器的权限
      - ALL
    cap_drop:  # 取消容器的权限
      - NET_ADMIN
volumes:  # 定义数据卷
  data: ~  # data 对应的数据卷为 zsg_data
networks:  # 定义网卡
  default:  # 默认的网卡
    name: aaa
  nwks:  # 自定义的网卡
    external: false  # false 将自动创建,true 必须先手动创建
挂载时使用 volume 和 bind 的区别,volume 是由 Docker Compose 维护和管理,新卷的内容可以由容器预先填充在 /var/lib/docker/volumes 目录下 。bind 可以自定义目录,便于修改,但首次挂载需要手动填充。

接下来会来一篇 Vim 的操作手册,等我学完~