镜像操作

镜像名称

首先来看下镜像的名称组成:

  • 镜名称一般分两部分组成:[repository]:[tag]。
  • 在没有指定 tag 时,默认是 latest,代表最新版本的镜像

    镜像命令

    常见的镜像操作命令如图:
    Docker 的基本操作 - 图1

    拉取、查看镜像

    需求:从 DockerHub 中拉取一个 Nginx 镜像并查看
  1. 首先去镜像仓库搜索 Nginx 镜像,比如 DockerHub:
  2. 根据查看到的镜像名称,拉取自己需要的镜像,通过命令:docker pull nginx
  3. 通过命令:docker images 查看拉取到的镜像

    保存镜像

    需求:利用 docker save 将 Nginx 镜像导出磁盘,然后再通过 load 加载回来

利用 docker xx --help 命令查看 docker savedocker load 的语法。例如,查看save命令用法,可以输入命令:

  1. docker save --help

命令格式:

docker save -o [保存的目标文件名称] [镜像名称]

使用 docker save 导出镜像到磁盘,运行命令:

docker save -o nginx.tar nginx:latest

导入镜像

先删除本地的 Nginx 镜像:

docker rmi nginx:latest

然后运行命令,加载本地文件:

docker load -i nginx.tar

容器操作

容器相关命令

容器操作的命令如图:Docker 的基本操作 - 图2
容器保护三个状态:

  • 运行:进程正常运行
  • 暂停:进程暂停,CPU 不再运行,并不释放内存
  • 停止:进程终止,回收进程占用的内存、CPU 等资源

其中:

  • docker run:创建并运行一个容器,处于运行状态
  • docker pause:让一个运行的容器暂停
  • docker unpause:让一个容器从暂停状态恢复运行
  • docker stop:停止一个运行的容器
  • docker start:让一个停止的容器再次运行
  • docker rm:删除一个容器
  • docker logs :查看容器日志的命令,添加 -f 参数可以持续查看日志
  • docker ps :查看容器状态,-a 查看所有容器,包括已经停止的

    创建并运行一个容器

创建并运行 Nginx 容器的命令:

docker run --name haloNginx -p 81:80 -d nginx

命令解读:

  • docker run :创建并运行一个容器
  • --name : 给容器起一个名字,比如叫做 haloNginx
  • -p :将宿主机端口与容器端口映射,冒号左侧是宿主机端口,右侧是容器端口
  • -d:后台运行容器
  • nginx:镜像名称,例如 nginx

这里的 -p 参数,是将容器端口映射到宿主机端口。

默认情况下,容器是隔离环境,我们直接访问宿主机的 81 端口,肯定访问不到容器中的 Nginx。

现在,将容器的 80 与宿主机的 81 关联起来,当我们访问宿主机的 81 端口时,就会被映射到容器的80,这样就能访问到 Nginx 了

进入容器并修改文件

需求:进入 Nginx 容器,修改 HTML 文件内容,添加“Halo World!”,进入容器要用到 docker exec 命令。

① 进入容器。进入我们刚刚创建的 Nginx 容器的命令为:

docker exec -it haloNginx bash

命令解读:

  • docker exec :进入容器内部,执行一个命令
  • -it : 给当前进入的容器创建一个标准输入、输出终端,允许我们与容器交互
  • haloNginx:要进入的容器的名称
  • bash:进入容器后执行的命令,bash 是一个 Linux 终端交互命令

② 进入 Nginx 的 HTML 所在目录 /usr/share/nginx/html

容器内部会模拟一个独立的 Linux 文件系统,看起来如同一个 Linux 服务器一样,Nginx 的环境、配置、运行文件全部都在这个文件系统中,包括我们要修改的 html 文件。

查看 DockerHub 网站中的 Nginx 页面,可以知道 Nginx 的 html 目录位置在 /usr/share/nginx/html,我们执行命令,进入该目录:

cd /usr/share/nginx/html

③ 修改 index.html 的内容,容器内没有 vi 命令,无法直接修改,我们用下面的命令来修改:

sed -i -e 's#Welcome to nginx#Halo World!#g' -e 's#<head>#<head><meta charset="utf-8">#g' index.html

数据卷(容器数据管理)

在之前的 Nginx 案例中,修改 Nginx 的 html 页面时,需要进入 Nginx 内部。并且因为没有编辑器,修改文件也很麻烦。

这就是因为容器与数据(容器内文件)耦合带来的后果。容器与数据耦合的问题:

  • 不便于修改:当我们要修改 Nginx 的 html 内容时,需要进入容器内部修改,很不方便。
  • 数据不可复用:在容器内的修改对外是不可见的。所有修改对新创建的容器是不可复用的。
  • 升级维护困难:数据在容器内,如果要升级容器必然删除旧容器,所有数据都跟着删除了

要解决这个问题,必须将数据与容器解耦,这就要用到数据卷了。

什么是数据卷

数据卷(volume)是一个虚拟目录,指向宿主机文件系统中的某个目录。一旦完成数据卷挂载,对容器的一切操作都会作用在数据卷对应的宿主机目录了。这样,我们操作宿主机的 /var/lib/docker/volumes/html 目录,就等于操作容器内的 /usr/share/nginx/html 目录了

数据集操作命令

数据卷操作的基本语法如下:

docker volume [COMMAND]

docker volume 命令是数据卷操作,根据命令后跟随的 command 来确定下一步的操作:

  • create :创建一个 volume
  • inspect :显示一个或多个 volume 的信息
  • ls :列出所有的 volume
  • prune :删除未使用的 volume
  • rm :删除一个或多个指定的 volume

    创建和查看数据卷

    ① 创建数据卷
    docker volume create nginx-html
    
    ② 查看所有数据
    docker volume ls
    
    ③ 查看数据卷详细信息卷
    docker volume inspect nginx-html
    
    可以看到,我们创建的 nginx-html 这个数据卷关联的宿主机目录为 /var/lib/docker/volumes/nginx-html/_data 目录。

    挂载数据卷

    我们在创建容器时,可以通过 -v 参数来挂载一个数据卷到某个容器内目录,命令格式如下:
    docker run \
    --name halo-nginx \
    -v nginx-html:/usr/share/nginx/html \
    -p 81:80
    nginx \
    
    这里的 -v 就是挂载数据卷的命令。-v nginx-html:/root/htm :把 nginx-html 数据卷挂载到容器内的 /root/html 这个目录中

需求:创建一个 Nginx 容器,修改容器内的 html 目录内的 index.html 内容

分析:上个案例中,我们进入 Nginx 容器内部,已经知道 Nginx 的 html 目录所在位置 /usr/share/nginx/html ,我们需要把这个目录挂载到 html 这个数据卷上,方便操作其中的内容。

① 创建容器并挂载数据卷到容器内的 HTML 目录

docker run --name halo-nginx -v nginx-html:/usr/share/nginx/html -p 81:80 -d nginx

② 进入 nginx-html 数据卷所在位置,并修改 HTML 内容

# 查看html数据卷的位置
docker volume inspect nginx-html
# 进入该目录
cd /var/lib/docker/volumes/nginx-html/_data
# 修改文件
vi index.html

数据卷不存在会自动创建

挂载本地目录

容器不仅仅可以挂载数据卷,也可以直接挂载到宿主机目录上。关联关系如下:

  • 带数据卷模式:宿主机目录 → 数据卷 → 容器内目录
  • 直接挂载模式:宿主机目录 → 容器内目录

目录挂载与数据卷挂载的语法是类似的:

  • -v [宿主机目录]:[容器内目录]
  • -v [宿主机文件]:[容器内文件]

需求:创建并运行一个 MySQL 容器,将宿主机目录直接挂载到容器

  1. 拉取 MySQL 镜像
  2. 创建目录 /develop/docker-volumes/halo-mysql/data
  3. 创建目录 /develop/docker-volumes/halo-mysql/conf ,并在其中创建 halo.conf,内容如下

    [mysqld]
    skip-name-resolve
    character_set_server=utf8
    datadir=/var/lib/mysql
    server-id=1000
    
  4. 进行挂载

    docker run \
    --name halo-mysql \
    -e MYSQL_ROOT_PASSWORD=halo \
    -p 3307:3306 \
    -v /develop/docker-volumes/halo-mysql/conf/halo.conf:/etc/mysql/conf.d/halo.conf \
    -v /develop/docker-volumes/halo-mysql/data:/var/lib/mysql \
    -d \
    mysql:latest