[Docker] - Docker 容器概念及命令

仓库、镜像和容器

学习 Docker 需要先了解三个概念:仓库、镜像、容器。

仓库是指 Docker 官方网站上的镜像仓库,镜像集中存放、管理场所。有点像 GitHub 那样的代码托管平台,用户可以上传自己的镜像到 Docker 官方的仓库,上传到仓库以后就可以随时随地的进行拉取。

镜像即一种封装好的东西,类似 .iso 文件,装过操作系统的应该都知道,我们从网上下载不同版本的 Window 操作系统,然后通过装机工具来安装,其实原理与 Docker 如出一辙,我们从网上下载镜像(操作系统镜像),通过 Docker 构建出对应的容器(操作系统)。

Docker 官方提供了许多基础镜像,而用户可以基于 Docker 官方提供的基础镜像二次创造出新的镜像,例如以 Centos 系统作为基础镜像,我们在上面又安装了 PHP、Nginx、MySQL,然后把安装了这些东西的镜像上传到官方仓库,那这个镜像就可以提供 WEB 服务器所需要的基本环境。

值得一提的是,Docker 中的基础镜像为了精简体积都是阉割版,只包含最核心的部分,因此有许多命令是没有安装的,比如 vim 之类的,它只提供了最基础的命令,如:findcat 等等。

容器是从镜像中创建、可以独立运行的软件包,容器就是镜像运行后的实体。比如上面举例的 WEB 服务器镜像,拉取下来直接运行,我们就可以得到创建镜像时一模一样的环境,就不需要每次重新安装 PHP、Nginx、MySQL 了。

基于镜像可以创建无数个容器,相当于克隆出无数份相同的东西。

官方镜像

官方指的是对某些领域负责的企业,如 Docker 会维护一些基础镜像和范例教程,所有的镜像都可以在 Docker 提供的仓库中搜索。

Docker 仓库:Docker Hub

官方镜像是比较具有可信度、长期维护的,使用 Docker 建议优先使用官方的镜像。

例如,ELK 官方提供了一整套的 docker 镜像:Docker ELK

如果官方镜像满足不了个人的定制要求(如操作系统必须是 Centos 之类的),那就可以自己构建一个镜像。

构建镜像

从官方拉取某种基础系统镜像(如 Centos、Ubuntu),运行镜像创建一个新的容器,进入容器内部,这个时候就可以开始 DIY 自己的容器了。

1、定制自己的容器

例如我们在容器里下载了某个东西,下载的东西就会留存在这个容器里面,容器的体积也会因此增大,需要及时删除不必要的东西。

在这个步骤就是安装自己想要的东西以及配置相关参数阶段。

假设我要自定义一个基于 Centos 系统的 PHP-FPM 镜像,那我就可以先下载 Docker 官方提供的 Centos 系统镜像,然后运行这个镜像,在容器内部执行一系列 yum 命令安装 PHP-FPM,然后再配置好文件,这样一个定制的 PHP-FPM 容器就完成了。

完成好容器内部的工作后,就可以基于这个容器生成镜像。

2、创建镜像

从指定容器中创建一个新的镜像:

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

OPTIONS 参数说明:

-a :提交的镜像作者;
-c :使用Dockerfile指令来创建镜像;
-m :提交时的说明文字;
-p :在commit时,将容器暂停。

示例:

docker commit -m "my image" -a "Huo tu" ca33381c3151 huotu:1.0

其中,-m 参数后面是提交时的说明,可以描述镜像信息;-a 参数是作者信息;ca33381c3151 是容器 ID,可以通过 docker ps -a 查看;huotu:1.0 是镜像名字及版本信息,镜像名字可以是组织或个人名字,取名参照:组织名字/软件名字,添加组织或个人名字可以用于区别不同的人上传相同的软件,例如上面我生成的镜像可以取名为:huotu/php-fpm:1.0,这样与官方的 php-fpm 就区分开来了,其他用户也可以根据名字找到想要的镜像。

3、推送到 Docker Hub

然后与 Git 一样,通过 push 命令上传到 Docker 仓库:

docker push [OPTIONS] NAME[:TAG]

Docker 每次在容器中操作,相当于写入一层新的东西,这是不可逆的,因此构建镜像的过程中应当尽量减少多余的命令并且检查是否有不需要的东西没有删除干净,如果不这么做,就会导致上传的镜像体积变得很大,拉取镜像会花更多的时间。

Login 登录验证

如果不是使用桌面版 Docker,有时需要身份验证了才能执行命令,需要登录到 Docker,使用命令 docker login 进行登录,需要提前到 Docker 官方网站进行注册。

PULL 命令

pull 命令可以从 Docker 官方仓库拉取镜像到本地。

docker pull [OPTIONS] NAME[:TAG|@DIGEST]

-a :拉取所有 tagged 镜像
--disable-content-trust :忽略镜像的校验,默认开启

示例:

docker pull ubuntu

如果不指定版本号,默认拉取最新版。

指定版本:

docker pull ubuntu:15.10

拉取官方仓库中的镜像完成后,使用 docker images 即可看到镜像。

RUN 命令

run 命令可以基于镜像(Image)创建一个新的容器(Container),如果镜像不存在则会自动执行 pull(拉取)镜像,然后再创建容器。

语法:

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

示例:

docker run 镜像名称[:镜像版本]

其中镜像版本可忽略,如果忽略则默认拉取最新版(latest),由于我们本地还没有下载过这个镜像,docker 会先拉取最新镜像:

FireRabbitdeMacBook-Pro:~ firerabbit$ docker run ubuntu
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
7ddbc47eeb70: Pull complete
c1bbdc448b72: Pull complete
8c3b70e39044: Pull complete
45d437916d57: Pull complete
Digest: sha256:6e9f67fa63b0323e9a1e587fd71c561ba48a034504fb804fd26fd8800039835d
Status: Downloaded newer image for ubuntu:latest

然后通过 docker images 获取当前已下载的镜像:

REPOSITORY                        TAG                 IMAGE ID            CREATED             SIZE
ubuntu                            latest              775349758637        4 weeks ago         64.2MB
  • REPOSITORY:仓库名称
  • TAG:标签,用来标识版本
  • IMAGE ID:镜像 ID,用来标识一个镜像,可以使用镜像 ID创建容器、删除镜像
  • CREATED:创建时间
  • SIZE:镜像大小

上面的命令没有任何参数,因此容器运行后马上就关了,我们可以通过 docker ps -a 命令(添加 -a 参数显示包含已停止运行的容器)找到已经停止运行的容器:

FireRabbitdeMacBook-Pro:~ firerabbit$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS               NAMES
c8fbcdd48250        ubuntu              "/bin/bash"              8 minutes ago       Exited (0) 8 minutes ago                        keen_antonelli

容器 ID 缩写方法:在 Docker 中 CONTAINER ID 即容器 ID,用来标识不同的容器,在使用 Docker 命令可以只取前面几个字符而不需要用完整的容器 ID,如上面例子中的容器 ID 为 c8fbcdd48250 那可以取前面任意字符:c、c8、c8f、c8fb 等等,只要没有重名的即可使用缩写。

可以通过添加第三个参数来执行容器内部命令:

docker run ubuntu /bin/echo "hello world"

由于每次 run 命令都会创建一个新的镜像,因此不推荐这么使用(见后文 EXEC 命令)。

上面的例子中,运行创建完容器就自动退出了,如果我们希望进入到容器内部,可以添加 it 两个参数:

docker run -it ubuntu

这样就可以进入到容器内部。

如果希望退出容器,有两种选择:

  • 退出容器的时候停止容器
  • 退出容器的时候,将容器转化为后台运行

使用 ctrl+d 快捷键可以退出容器并且将容器停止,如果希望退出容器后不停止,可以使用 ctrl+q+p 快捷键。

如果容器保持在后台运行,可以使用 docker ps 看到正在后台运行的容器。

添加 -d 参数可以不进入容器,直接让容器在后台运行:

docker run -itd ubuntu

宿主机

安装 Docker 的机子叫宿主机,相当于 Docker 寄宿在这个机子上,宿主机和容器默认是隔离的,如果需要进行通讯就需要进行端口映射。

端口映射

添加 -p 参数可以将宿主机的端口映射到容器的端口。

示例:

docker run -itd -p 8088:80 ubuntu

上面的例子将宿主机的 8088 端口与容器的 80 端口进行映射,这个时候访问宿主机的 8088 端口相当于在访问容器的 80 端口。

docker ps 命令可以看到映射关系:

image.png

在 Nginx 或者 PHP-FPM、MySQL 这些提供服务的容器,经常需要用到端口映射。

数据卷

如果我们运行了一个 Nginx 容器,但是我们需要把容器内部的文件,如访问日志、错误日志保存在宿主机,那应该如果去做呢?

可以使用“卷”将宿主机与容器进行文件映射,使用参数 -v

示例:

docker run -it -v ~/data:/var/data ubuntu

上面的例子将宿主机的 ~/data 目录与容器的 /var/data 进行了映射,如果宿主机不存在这个文件夹,则会自动创建一个,这个文件夹里面的内容就是容器内部的文件。

全部可选参数

-a stdin: 指定标准输入输出内容类型,可选 STDIN/STDOUT/STDERR 三项;

-d: 后台运行容器,并返回容器ID;

-i: 以交互模式运行容器,通常与 -t 同时使用;

-P: 随机端口映射,容器内部端口随机映射到主机的高端口

-p: 指定端口映射,格式为:主机(宿主)端口:容器端口

-t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用;

--name="nginx-lb": 为容器指定一个名称;

--dns 8.8.8.8: 指定容器使用的DNS服务器,默认和宿主一致;

--dns-search example.com: 指定容器DNS搜索域名,默认和宿主一致;

-h "mars": 指定容器的hostname;

-e username="ritchie": 设置环境变量;

--env-file=[]: 从指定文件读入环境变量;

--cpuset="0-2" or --cpuset="0,1,2": 绑定容器到指定CPU运行;

-m :设置容器使用内存最大值;

--net="bridge": 指定容器的网络连接类型,支持 bridge/host/none/container: 四种类型;

--link=[]: 添加链接到另一个容器;

--expose=[]: 开放一个端口或一组端口;

--volume , -v: 绑定一个卷

EXEC 命令

上面的例子:

docker run ubuntu /bin/echo "hello world"

这会创建一个新的容器占用空间,为了避免这种情况,我们可以使用 exec 命令。

exec 命令是基于已有的容器运行命令,它不会像 run 那样每次运行就要创建一个新的容器。

示例:

docker exec 3aa /bin/echo "hello world"

以 ID 为 3aa 开头的容器运行命令输出 hello world。

如果需要进入到一个正在运行的容器里,也可以使用 exec 命令。

docker exec -it 3aa /bin/bash

在这里执行了 /bin/bash 进入容器的 bash 环境。

STOP 停止命令

使用 docker stop 容器ID 来停止一个正在运行的容器。

删除容器/镜像

使用 docker rm 容器ID 删除一个停止状态的容器,如果容器在后台运行,需要先停止才能删除。

使用 docker rmi 镜像ID 删除一个镜像,如果该镜像有许多依赖关系,则需要逐个删除依赖关系才能删掉这个镜像。

当容器较多时,一个个删除十分麻烦,可以参考:批量删除容器

Inspect 检查容器

有时需要查看容器的各项参数,可以使用 docker inspect [OPTIONS] NAME|ID [NAME|ID...] 命令。

可选参数:

-f :指定返回值的模板文件。

-s :显示总的文件大小。

--type :为指定类型返回JSON。

示例:

docker inspect cf8

这里使用了容器 ID 缩写的方式,cf8 即容器 ID 前面 3 个字符。

启动/重启容器

使用 run 命令启动的容器被停止以后,可以将其重新激活,使用 docker start 容器ID 启动一个已经停止的容器,启动后的容器会转化为后台运行状态。

使用 docker restart 容器ID 来重启一个容器。

讨论

还没有人评论~