docker容器笔记

306 阅读16分钟

基本介绍

虚拟机问题

虚拟机是带环境安装的一种解决方案。它可以在一种操作系统里面运行另一种操作系统,比如在Windows系统里面运行Linux系统。应用程序对此毫无感知,因为虚拟机看上去跟真实系统一模一样,而对于底层系统来说,虚拟机就是一个普通文件,不需要了就删掉,对其他部分毫无影响。 虽然用户可以通过虚拟机还原软件的原始环境。但是,这个方案有几个缺点。

  • 资源占用多 虚拟机会独占一部分内存和硬盘空间。它运行的时候,其他程序就不能使用这些资源了。哪怕虚拟机里面的应用程序,真正使用的内存只有 1MB,虚拟机依然需要几百 MB 的内存才能运行。
  • 冗余步骤多 虚拟机是完整的操作系统,一些系统级别的操作步骤,往往无法跳过,比如用户登录。
  • 启动慢 启动操作系统需要多久,启动虚拟机就需要多久。可能要等几分钟,应用程序才能真正运行。

容器优点

我们可以把它看成虚拟机,能在一台服务器上隔离出若干个互不干扰的环境。把自己的应用放入容器还可以进行版本管理、复制、分享、修改,就像管理普通的代码一样。它具有启动快、资源占用少、体积小、易操作等等。相比虚拟机有很多优势。

概念

Image 镜像

什么是Docker镜像?简单的理解,Docker镜像就是一个Linux文件系统(Root FileSystem),这个文件系统里面包含可以运行在Linux内核的程序以及相应的数据。

通过镜像启动一个容器,一个镜像就是一个可执行的包,其中包括运行应用程序所需要的所有内容:包含代码,运行时间,库,环境变量和配置文件等。

Docker 把 App 文件打包成为一个镜像,并且采用类似多次快照的存储技术,可以实现:

  • 多个App可以共用相同的底层镜像(初始的操作系统镜像);
  • App运行时的IO操作和镜像文件隔离;
  • 通过挂载包含不同配置/数据文件的目录或者卷(Volume),单个App镜像可以用来运行无数个不同业务的容器。

Container 容器

镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。

Docker面向对象
镜像
容器对象

镜像分层

Docker 支持通过扩展现有镜像,创建新的镜像。实际上,Docker Hub99%的镜像都是通过在base镜像中安装和配置需要的软件构建出来的。

docker

从上图可以看到,新镜像是从base镜像一层一层叠加生成的。每安装一个软件,就在现有镜像的基础上增加一层。

镜像分层最大的一个好处就是共享资源。比如说有多个镜像都从相同的base镜像构建而来,那么Docker Host只需在磁盘上保存一份base镜像;同时内存中也只需加载一份base镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。

如果多个容器共享一份基础镜像,当某个容器修改了基础镜像的内容,比如/etc下的文件,这时其他容器的/etc是不会被修改的,修改只会被限制在单个容器内。这就是容器Copy-on-Write特性。

Volume 数据卷

实际上我们的容器就好像是一个简易版的操作系统,只不过系统中只安装了我们的程序运行所需要的环境,前边说到我们的容器是可以删除的,那如果删除了,容器中的程序产生的需要持久化的数据怎么办呢?容器运行的时候我们可以进容器去查看,容器一旦删除就什么都没有了。

所以数据卷就是来解决这个问题的,是用来将数据持久化到我们宿主机上,与容器间实现数据共享,简单的说就是将宿主机的目录映射到容器中的目录,应用程序在容器中的目录读写数据会同步到宿主机上,这样容器产生的数据就可以持久化了,比如我们的数据库容器,就可以把数据存储到我们宿主机上的真实磁盘中。

镜像命令

官方文档:docs.docker.com/reference

查看镜像

执行命令:docker images

属性说明
REPOSITORY镜像在仓库中的名称
TAG镜像标签
IMAGE ID镜像 ID
CREATED镜像的创建日期
SIZE镜像大小

这些镜像都是存储在Docker宿主机的/var/lib/docker目录下。

搜索镜像

如果你需要从网络中查找需要的镜像,可以通过以下命令搜索。

执行命令:docker search 镜像名称

属性说明
NAME镜像名称
DESCRIPTION镜像描述
STARS用户评价
OFFICIAL是否为官方构建
AUTOMATEDDocker Hub 自动构建

拉取镜像

拉取镜像就是从中央仓库下载镜像到本地。

执行命令:docker pull 镜像名称

如果不声明tag镜像标签信息则默认拉取latest版本。

删除镜像

按镜像ID删除单个镜像。

执行命令:docker rmi 镜像ID

按镜像ID删除多个镜像。

执行命令:docker rmi 镜像ID 镜像ID 镜像ID

docker images -q可以查询到所有镜像的ID,通过组合命令可以实现删除所有镜像的操作。

执行命令:docker rmi docker images -q

注意:如果通过某个镜像创建了容器,则该镜像无法删除。 解决办法:先删除镜像中的容器,再删除该镜像。

容器命令

查看容器

查看正在运行的容器。

执行命令:docker ps

属性说明
CONTAINER ID容器 ID
IMAGE所属镜像
COMMAND启动容器时运行的命令
CREATED创建时间
STATUS容器状态
PORTS端口
NAMES容器名称

查看停止的容器。

执行命令:docker ps -f status=exited

查看所有容器(包括运行和停止)。

执行命令:docker ps -a

查看最后一次运行的容器。

执行命令:docker ps -l

列出最近创建的 n 个容器。

执行命令:docker ps -n 5

创建与启动容器

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

  • -i:表示运行容器;
  • -t:表示容器启动后会进入其命令行。加入这两个参数后,容器创建就能登录进去。即分配一个伪终端;
  • --name:为创建的容器命名;
  • -v:表示目录映射关系(前者是宿主机目录,后者是映射到宿主机上的目录),可以使用多个 -v 做多个目录或文件映射。注意:最好做目录映射,在宿主机上做修改,然后共享到容器上;
  • -d:在 run 后面加上 -d 参数,则会创建一个守护式容器在后台运行(这样创建容器后不会自动登录容器,如果只加 -i -t 两个参数,创建容器后就会自动进容器里);
  • -p:表示端口映射,前者是宿主机端口,后者是容器内的映射端口。可以使用多个 -p 做多个端口映射。
  • -P:随机使用宿主机的可用端口与容器内暴露的端口映射。

创建并进入容器

下面这行命令的意思就是通过镜像 AA 创建一个容器 BB,运行容器并进入容器的/bin/bash

docker run -it --name 容器名称 镜像名称:标签 /bin/bash

注意:Docker容器运行必须有一个前台进程,如果没有前台进程执行,容器认为是空闲状态,就会自动退出。

退出当前容器

exit

守护式方式创建容器

docker run -di --name 容器名称 镜像名称:标签

登录守护式容器方式

docker exec -it 容器名称|容器ID /bin/bash

停止与启动容器

# 停止容器
docker stop 容器名称|容器ID

# 启动容器
docker start 容器名称|容器ID

文件拷贝

如果我们需要将文件拷贝到容器内可以使用cp命令。

docker cp 需要拷贝的文件或目录 容器名称:容器目录

也可以将文件从容器内拷贝出来。

docker cp 容器名称:容器目录 需要拷贝的文件或目录

目录挂载

我们可以在创建容器的时候,将宿主机的目录与容器内的目录进行映射,这样我们就可以通过修改宿主机某个目录的文件从而去影响容器,而且这个操作是双向绑定的,也就是说容器内的操作也会影响到宿主机,实现备份功能。

但是容器被删除的时候,宿主机的内容并不会被删除。如果多个容器挂载同一个目录,其中一个容器被删除,其他容器的内容也不会受到影响。

创建容器添加-v参数,格式为宿主机目录:容器目录,例如:

docker run -di -v /home/ruoyi/data:/usr/local/data --name centos7-01 centos:7

# 多目录挂载
docker run -di -v /宿主机目录:/容器目录 -v /宿主机目录2:/容器目录2 镜像名
  • 匿名挂载

匿名挂载只需要写容器目录即可,容器外对应的目录会在/var/lib/docker/volumes中生成。

# 匿名挂载
docker run -di -v /usr/local/data --name centos7-02 centos:7
# 查看 volume 数据卷信息
docker volume ls
  • 具名挂载

具名挂载就是给数据卷起了个名字,容器外对应的目录会在/var/lib/docker/volume中生成。

# 匿名挂载
docker run -di -v docker_centos_data:/usr/local/data --name centos7-03 centos:7
# 查看 volume 数据卷信息
docker volume ls
  • 指定目录挂载

之前挂载方式就属于指定目录挂载,这种方式的挂载不会在/var/lib/docker/volume目录生成内容。

docker run -di -v /mydata/docker_centos/data:/usr/local/data --name centos7-01 centos:7
# 多目录挂载
docker run -di -v /宿主机目录:/容器目录 -v /宿主机目录2:/容器目录2 镜像名
  • 查看目录挂载关系

通过docker volume inspect数据卷名称 可以查看该数据卷对应宿主机的目录地址。

执行命令:docker volume inspect docker_centos_data

通过docker inspect容器ID或名称 ,在返回的JSON节点中找到Mounts,可以查看详细的数据挂载信息。

  • 只读/读写
# 只读。只能通过修改宿主机内容实现对容器的数据管理。
docker run -it -v /宿主机目录:/容器目录:ro 镜像名

# 读写,默认。宿主机和容器可以双向操作数据。
docker run -it -v /宿主机目录:/容器目录:rw 镜像名

删除容器

# 删除指定容器
docker rm 容器名称|容器ID

# 删除多个容器
docker rm 容器名称|容器ID 容器名称|容器ID

Dockerfile

Docker中构建镜像最常用的方式,就是使用DockerfileDockerfile是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。官方文档:docs.docker.com/engine/refe…

Dockerfile 常用指令

指令语法说明
FROMFROM <image>:<tag>指明构建的新镜像是来自于哪个基础镜像,如果没有选择tag,那么默认值为latest
MAINTAINERMAINTAINER <name>指明镜像维护者及其联系方式(一般是邮箱地址)。官方说明已过时,推荐使用LABEL
LABELLABEL <key>=<value> ...功能是为镜像指定标签。也可以使用LABEL来指定镜像作者
RUNRUN <command>构建镜像时运行的Shell命令,比如构建的新镜像中我们想在/usr/local目录下创建一个java目录
ADDADD <src>... <dest>拷贝文件或目录到镜像中。src 可以是一个本地文件,还可以是一个url。然后自动下载和解压
COPYCOPY <src>... <dest>拷贝文件或目录到镜像中。用法同 ADD,只是不支持自动下载和解压
EXPOSEEXPOSE <port> [<port>/<protocol>...]暴露容器运行时的监听端口给外部,可以指定端口是监听 TCP 还是 UDP,如果未指定协议,则默认为 TCP
ENVENV <key>=<value> ...设置容器内环境变量
CMDCMD ["executable","param1","param2"]启动容器时执行的Shell命令。在Dockerfile中只能有一条CMD指令。如果设置了多条CMD,只有最后一条会生效
ENTRYPOINTENTRYPOINT ["executable", "param1", "param2"]启动容器时执行的 Shell 命令,同 CMD 类似,不会被 docker run 命令行指定的参数所覆盖,如果设置了多条ENTRYPOINT,只有最后一条会生效
WORKDIRWORKDIR param为 RUN、CMD、ENTRYPOINT 以及 COPY 和 AND 设置工作目录
VOLUMEVOLUME ["param"]指定容器挂载点到宿主机自动生成的目录或其他容器。一般的使用场景为需要持久化存储数据时

构建镜像

Dockerfile文件编写好以后,真正构建镜像时需要通过docker build命令。

docker build命令用于使用Dockerfile创建镜像。

# 使用当前目录的 Dockerfile 创建镜像
docker build -t mycentos:7 .

# 通过 -f Dockerfile 文件的位置创建镜像
docker build -f /home/ruoyi/docker/Dockerfile -t mycentos:7 .
  • -f:指定要使用的 Dockerfile 路径;
  • --tag, -t:镜像的名字及标签,可以在一次构建中为一个镜像设置多个标签。

Docker Compose

通过前面几篇文章的学习,我们可以通过Dockerfile文件让用户很方便的定义一个单独的应用容器。然而,在日常工作中,经常会碰到需要多个容器相互配合来完成某项任务的情况,或者开发一个Web应用,除了Web服务容器本身,还需要数据库服务容器、缓存容器,甚至还包括负载均衡容器等等。

Docker Compose恰好满足了这样的需求,它是用于定义和运行多容器Docker应用程序的工具。通过Compose,您可以使用YAML文件来配置应用程序所需要的服务。然后使用一个命令,就可以通过YAML配置文件创建并启动所有服务。

Compose 常用命令

官方文档:https://docs.docker.com/compose/reference/overview/

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

部分命令选项如下:

  • -f,--file:指定使用的 Compose 模板文件,默认为 docker-compose.yml,可以多次指定,指定多个 yml;
  • -p, --project-name:指定工程名称,默认使用 docker-compose.yml 文件所在目录的名称;
  • -v:打印版本并退出;
  • --log-level:定义日志等级(DEBUG, INFO, WARNING, ERROR, CRITICAL)。

help

docker-compose -help查看帮助。

config

docker-compose config -q验证docker-compose.yml文件。当配置正确时,不输出任何内容,当配置错误时,输出错误信息。

pull

docker-compose pull拉取服务依赖的镜像。

# 拉取工程中所有服务依赖的镜像
docker-compose pull
# 拉取工程中 nginx 服务依赖的镜像
docker-compose pull nginx
# 拉取镜像过程中不打印拉取进度信息
docker-compose pull -q

up

docker-compose up创建并启动所有服务的容器。指定多个yml-f选项。以守护进程模式运行加-d选项。

# 前台启动
docker-compose up
# 后台启动
docker-compose up -d
# -f 指定使用的 Compose 模板文件,默认为 docker-compose.yml,可以多次指定,指定多个 yml
docker-compose -f docker-compose.yml up -d 

logs

docker-compose logs查看服务容器的输出日志。默认情况下,docker-compose将对不同的服务输出使用不同的颜色来区分。可以通过--no-color来关闭颜色。

# 输出日志,不同的服务输出使用不同的颜色来区分
docker-compose logs
# 跟踪日志输出
docker-compose logs -f
# 关闭颜色
docker-compose logs --no-color

ps

docker-compose ps列出工程中所有服务的容器。

# 列出工程中所有服务的容器
docker-compose ps
# 列出工程中指定服务的容器
docker-compose ps nginx

run

docker-compose run在指定服务容器上执行一个命令。

# 在工程中指定服务的容器上执行 echo "helloworld"
docker-compose run nginx echo "helloworld"

exec

docker-compose exec进入服务容器。

# 进入工程中指定服务的容器
docker-compose exec nginx bash
# 当一个服务拥有多个容器时,可通过 --index 参数进入到该服务下的任何容器
docker-compose exec --index=1 nginx bash

pause

docker-compose pause暂停服务容器

# 暂停工程中所有服务的容器
docker-compose pause
# 暂停工程中指定服务的容器
docker-compose pause nginx

unpause

docker-compose unpause恢复服务容器。

# 恢复工程中所有服务的容器
docker-compose unpause
# 恢复工程中指定服务的容器
docker-compose unpause nginx

restart

docker-compose restart重启服务容器。

# 重启工程中所有服务的容器
docker-compose restart
# 重启工程中指定服务的容器
docker-compose restart nginx

start

docker-compose start启动服务容器。

# 启动工程中所有服务的容器
docker-compose start
# 启动工程中指定服务的容器
docker-compose start nginx

stop

docker-compose stop停止服务容器。

# 停止工程中所有服务的容器
docker-compose stop
# 停止工程中指定服务的容器
docker-compose stop nginx

kill

docker-compose kill通过发送SIGKILL信号停止指定服务的容器。

# 通过发送 SIGKILL 信号停止工程中指定服务的容器
docker-compose kill nginx

rm

docker-compose rm 删除服务(停止状态)容器。

# 删除所有(停止状态)服务的容器
docker-compose rm
# 先停止所有服务的容器,再删除所有服务的容器
docker-compose rm -s
# 不询问是否删除,直接删除
docker-compose rm -f
# 删除服务容器挂载的数据卷
docker-compose rm -v
# 删除工程中指定服务的容器
docker-compose rm -sv nginx

down

停止并删除所有服务的容器、网络、镜像、数据卷。

# 停止并删除工程中所有服务的容器、网络
docker-compose stop
# 停止并删除工程中所有服务的容器、网络、镜像
docker-compose down --rmi all
# 停止并删除工程中所有服务的容器、网络、数据卷
docker-compose down -v

images

docker-compose images打印服务容器所对应的镜像。

# 打印所有服务的容器所对应的镜像
docker-compose images
# 打印指定服务的容器所对应的镜像
docker-compose images nginx

port

docker-compose port打印指定服务容器的某个端口所映射的宿主机端口。

docker-compose port nginx 80

top

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

# 显示工程中所有服务的容器正在运行的进程
docker-compose top
# 显示工程中指定服务的容器正在运行的进程
docker-compose top nginx

参考