Docker学习笔记 | 青训营

82 阅读9分钟

Docker

一个开源的应用容器引擎,解决软件跨环境迁移问题

Docker概念

  • 将应用和依赖打包到一个轻量级、可移植的容器中,然后发布到任何流行的Linux机器上
  • 容器采用沙箱机制,互相隔离
  • 启动容器的开销极低

Docker架构

  • 镜像(Image):相当于一个root文件系统
  • 容器(Container):容器是镜像运行时的实体,可以被创建、启动、停止、删除、暂停等
  • 仓库(Repository):用来保存镜像的一个代码控制中心

配置Docker镜像加速器

阿里云 -> 控制台 -> 左上角导航 -> “产品与服务”中搜索“镜像” -> 选择“容器镜像服务“ -> 镜像工具 -> 镜像加速器 -> 复制命令到终端

Docker命令

服务相关命令

控制Docker守护进程

  • 启动:systemctl start docker
  • 停止:systemctl stop docker
  • 重启:systemctl restart docker
  • 查看状态:systemctl status docker
  • 开机自启:systemctl enable docker

镜像相关命令

操作本地和中央仓库中的镜像

  • 查看本地的镜像:docker images

  • 查看本地的镜像ID:docker images -q

  • 搜索中央仓库中的镜像:docker search 镜像名

  • 拉取镜像到本地仓库:docker pull 镜像名[:版本号]

    • 不写版本号,则默认使用latest版本
    • 可以去官网查询有哪些可下载的版本
  • 删除指定的本地镜像:

    • 通过镜像ID:docker rmi 镜像ID
    • 通过镜像名+版本号:docker rmi 镜像名:版本号
  • 删除所有本地镜像:

    docker rmi `docker images -q`
    

    注意:这里用的时Tab键上面的那个符号而不是单引号,表示将查询结果作为参数传给删除命令

容器相关命令

  • 查看容器:

    • 查看正在运行的容器:docker ps
    • 查看所有容器:docker ps -a
  • 创建并启动容器:docker run 参数

    • 参数说明:

      • -i:保持容器运行

      • -t:为容器分配一个伪输入终端。

        可以与-i一起使用,即-it,称为交互式容器。该容器创建后自动进入容器,使用exit退出容器后,容器自动关闭

      • -d:以守护(后台)模式运行容器。

        可以与-i一起使用,即-id,称为守护式容器。该容器创建后在后台运行,需要用docker exec -it 容器名 /bin/bash命令进入容器;退出后容器不会自动关闭

      • --name=容器名--name 容器名:为容器取一个名字

    • 完整命令举例:

      • docker run -it --name=c1 redis:6 /bin/bash
      • docker run -id --name=c2 redis:6
  • 进入容器:docker exec 参数 容器名

  • 启动容器:docker start 容器名

  • 停止容器:docker stop 容器名

  • 删除容器:docker rm 容器名/容器ID

  • 产看容器信息:docker inspect 容器名

数据卷

数据卷的概念

  1. 什么是数据卷?
    • 数据卷是宿主机的一个目录或文件
    • 当容器的目录或文件与数据卷绑定后,双方的任何一方的修改都会立即同步到另一方
    • 一个数据卷可以被多个容器同时挂载
    • 一个容器也可以挂载多个数据卷
  2. 数据卷有什么用?
    • 容器数据持久化:容器中的数据在容器销毁之后仍然可以通过数据卷获取到
    • 实现容器和外部机器的间接通信
    • 实现容器之间的数据交换

配置数据卷

  • 创建并启动容器时,使用-v参数设置数据卷:docker run ... -v 宿主机目录(文件):容器目录(文件)...
    • 目录必须是绝对路径
    • 如果目录不存在,会自动创建
    • 可以挂载多个数据卷(同一条命令中多次使用-v即可)

数据卷容器

当多个容器与数据卷的绑定方式相同时,可以简化配置操作

  • 创建数据卷容器:创建方式与创建普通容器并配置数据卷映射一致,该容器相当于提供了一种容器目录:宿主机目录的映射关系模板,其他容器可以通过这个数据卷容器快捷配置与宿主机数据卷的映射关系

  • 通过数据卷容器,快捷配置其他容器:

    例如:docker run -it --name=c1 --volumes-from c3 centos:7。其中c3是数据卷容器,而c1通过--volumes-from参数使用了c3的配置作为自身的配置

Docker应用部署举例

MySQL

  1. 拉取镜像

  2. 创建容器、设置端口映射(宿主机端口:容器端口)、数据卷映射

    mkdir ~/mysql
    cd ~/mysql
    docker run -id --name=c_mysql \
    -p 3306:3306 \
    -v $PWD/conf:/etc/mysql/conf.d \
    -v $PWD/logs:/logs \
    -v $PWD/data:/var/lib/mysql \
    -e MYSQL_ROOT_PASSWORD=123456 \
    mysql:5.7
    

Dockerfile

Docker镜像的原理

Docker镜像的本质是一个分层的文件系统

  • Docker镜像是由特殊的文件系统叠加而成
  • 最底端使用的是宿主机的bootfs
  • 第二层是root文件系统rootfs,称为base image,决定了linux是哪个发行版
  • 再往上可以叠加其他镜像文件
  • 统一文件系统(Union File System)技术可以将这些层整合为一个文件系统,隐藏了多层的存在,在用户看来就是一个文件系统
  • 一个镜像可以放在另一个镜像上,下面的镜像称为父镜像,最底部的镜像称为基础镜像
  • 这种镜像叠加的方法,极大提高了复用性(例如当前镜像需要使用的某一层已经在另一个镜像中加载过了,那么可以直接复用,无需重新加载)
  • 当从一个镜像启动容器时,Docker会在顶层加载一个读写文件系统作为容器

如何制作Docker镜像?

1. 容器转为镜像

这种方法不够灵活和透明,十分不利于后期维护,不推荐

  • 容器→镜像:docker commit 容器id 镜像名称:版本号(不写版本号则默认是latest)
  • 镜像→压缩文件:docker save -o 压缩文件名称 镜像名称:版本号
  • 压缩文件→镜像:docker load -i 压缩文件名称

注意:如果容器使用数据卷挂载的方式存储了一些数据,那么在转为镜像后,这些数据将不会打包在镜像里

2. Dockerfile

2.1 关键字
关键字作用备注
FROM指定父镜像指定dockerfile 基于哪个image构建
MAINTAINER作者信息
LABEL标签
RUN执行命令默认用/bin/sh
格式1:RUN command
格式2:RUN ["command","param1","param2"]
CMD容器启动命令容器启动时的的默认命令
格式1:CMD command
格式2:CMD ["command","param1","param2"]
ENTRYPOINT入口
COPY复制文件build的时候复制文件到image中(不会自动解压缩)
ADD添加文件build的时候添加文件到image中(自动解压缩)
不局限于当前build的上下文,可以来源于远程服务
ENV环境变量可以在启动容器时通过-e ENV名称=value参数进行覆盖
ARG构建参数如果有ENV,那么相同名字的ENV的值始终覆盖ARG的参数
VOLUME定义外部可以挂载的数据卷
EXPOSE暴露端口
WORKDIR工作目录进入容器时停留的位置,如果没有创建则自动创建
如果指定/
USER指定执行用户指定build或启动时的用户,是RUNCMDENTRYPOINT执行时的用户
HEALTHCHECK健康检查
ONBUILD触发器
STOPSIGNAL发送信号量到宿主机
SHELL指定执行脚本的shell
2.2 书写规则
  • 每个关键字对应的“一行”,都会成为镜像中的“一层”
  • 第一行必须是FROM语句,指明基础镜像。如果没有基础镜像(例如centos镜像的dockerfile文件中),则使用FROM scratch,其中scratch是一个特殊的虚拟镜像,表示空镜像
  • 尽量将多行脚本语句写在一个RUN后面,而不是使用多个RUN,防止产生过多的层
2.3 使用dockerfile文件构建镜像

docker build [参数] <上下文路径/URL/->

  • 参数:

    • -f:指定dockerfile文件的路径

    • -t:指定镜像名和版本号,-t 镜像名:版本号

  • 上下文(context):由于docker客户端和服务器引擎采用C/S模式,客户端实际上是在调用服务器引擎的REST API。逻辑上客户端和服务端是分离的,如果客户端希望把所需文件也打包进镜像中,就必须将这些文件发送给服务端。客户端需要把所有文件放在一个目录下,而这个目录就是所谓的上下文。在build指令的最后,需要指定上下文路径。

Docker服务编排

安装和卸载

# 安装
curl -L https://github.com/docker/compose/releases/download/2.18.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
# 设置文件可执行权限
chmod +x /usr/local/bin/docker-compose
# 查看版本信息
docker-compose -v
# 卸载
rm /usr/local/bin/docker-compose

使用docker-compose

Docker私有仓库

搭建私有仓库

# 1.拉取私有仓库镜像
docker pull registry
# 2.启动私有仓库容器
docker run -id --name=registry -p 5000:5000 registry
# 3.修改daemon.json
vim /etc/docker/daemon.json
# 在文件中添加一个key,用于让docker信任私有仓库地址,注意将私有仓库服务器ip地址修改为真实ip
{"insecure-registries":["私有仓库服务器ip地址:5000"]}
# 4.重启docker服务
systemctl restart docker

将镜像上传至私有仓库

# 1.标记镜像为私有仓库的镜像
docker tag app:latest 私有仓库服务器ip地址:5000/app:latest

# 2.上传标记的镜像
docker push 私有仓库服务器ip地址:5000/app:latest

从私有仓库拉取镜像

docker pull 私有仓库服务器ip地址:5000/app:latest

Docker容器虚拟化 vs 传统虚拟机

  • 相同:容器和虚拟机具有相似的资源隔离和分配的优势
  • 不同:
    • 容器虚拟化的是操作系统,虚拟机虚拟化的是硬件
    • 传统虚拟机可以运行不同的操作系统,容器只能运行同一类的操作系统
特性容器虚拟机
启动秒级分级
硬盘使用一般为MB一般为GB
性能接近原生弱于
系统支持量单机支持上千个容器一般几十个