浅尝 Docker
序
嗯,未雨绸缪,提前学一下怎么玩 docker 。
卷死他们
docker 是什么?
一般的虚拟机需要安装整个操作系统,会对我们的计算机占用大量的资源,而 docker 只需要模拟出项目所需要的运行环境,占用率非常低,这可以大大提高开发效率。
它可以按照我们的需求模拟出软件环境,并且能够快速部署我们开发好的项目实例(比如 Mastodon),并且一定程度上它具有环境隔离功能,运行环境与操作系统相分离,而且可以同时运行多个容器。
并且我们可以把容器封装成镜像,进行反复利用。
就像这条运着集装箱的鲸鱼一样,游到哪都是开箱即用。
怎么安装 docker
各个平台装 docker 都非常简单。
Linux 平台可能对初学者稍微难一些,但是对熟悉的用户来说, Linux 安装 docker 非常快。
直接从相应发行版的包管理器安装就行。
Arch
比如咱 Arch 可以让 pacman 把这条鲸鱼给带回来。
|
|
如果运行时出现以下报错
|
|
请使用 systemctl
启动 docker
的系统进程。
|
|
如果有必要,设置其开机自启
|
|
Debian
如果是用 deb 系的发行版,可以参考官方文档用 apt 来安装。
设置仓库
- 更新 apt 仓库,并安装一些依赖来允许 apt 通过 https 使用第三方仓库。
|
|
|
|
- 添加 Docker 官方 GPG 密钥
|
|
|
|
- 设置 Docker 仓库
|
|
安装 docker
- 更新软件包仓库
|
|
如果更新的时候发生了 GPG 错误,可以参考官网的这个提示:
Your default umask may be incorrectly configured, preventing detection of the repository public key file. Try granting read permission for the Docker public key file before updating the package index:
|
|
- 安装 Docker Engine 、 containerd 和 Docker Compose.
|
|
- 通过运行 hello-world 镜像来验证 docker 是否安装成功
|
|
rpm 系列
其实说实话,这类发行版我个人不太喜欢,就拿 CentOS 为例吧,CentOS 7 以上的版本也是可以直接用 yum 安装的。
设置仓库
一样是设置第三方仓库。
不过要先安装 yum-utils
才能用 yum-config-manager
。
|
|
然后设置仓库
|
|
安装
一样是使用 yum 命令来安装 docker 的软件包和依赖。
|
|
对于 Linux 平台再提一嘴
上述的方法都是在 Linux 平台安装 docker 的最新版本,如果需要安装特定的版本,可以参考 docker 的官方文档进行操作。
Windows
在 Windows 平台可以直接安装 docker-desktop,这也非常简单,直接通过 docker 官方文档下载安装包就行了。
我能怎么玩 docker?
docker 能干的事多着呢。
最常用的就是在 docker 容器里运行应用程序了。
HelloWorld
比如我们来运行一个 Hello World
|
|
如图所见,它输出一系列字符后,在最后输出了 hello world
那么来解释一下命令的含义吧
docker
– 运行 docker 的二进制文件, 这个没什么好说的run
– 运行容器ubuntu
– 要运行的镜像名称/bin/echo "hello world"
- 在容器里面要执行的命令
如果出现了以下信息,可能是因为在启动容器的时候没有下载好相关的镜像
|
|
默认情况下 docker 会自动下载,但最好养成启动之前下载好镜像的习惯。
|
|
交互式容器
当然,我们也可以创建一个可以交互的容器,意思就是可以用 bash 来控制它
|
|
-i
: 交互式操作。-t
: 终端。
这样我们创建容器之后,我们的 shell 也变成了容器里的 shell
我们可以对它进行一些操作命令,随便打几个吧.
而且我们执行的命令是不会影响到主系统的
然后我们可以使用 exit
命令来退出这个系统.
这样一来容器的操作系统就退出了,同时容器也停止运行了, 因为这个容器不是以 daemon 模式来运行的.
以 daemon 模式来运行容器
接下来我要说的是,为啥上文中用 exit
退出容器 shell 之后还不算完.
这次我们再打开一个容器,不过这次加一个参数 -d
这个参数的意思是以 Daemon 模式运行, 那么 Daemon 是什么意思呢?
通过搜索引擎得到的答案往往是什么 系统守护进程巴拉巴拉的,其实它类似于后台运行的意思.
接下来我们用这个命令来开个容器
|
|
这时我们发现,我们并没有得一个 shell, 而是得到来一串字符串.
我们试试用 docker 的 ps 命令来查看一下正在运行的容器:
|
|
我们得到来这样的结果
图片可能不太清楚? 这里还是贴出来吧
|
|
然后发现了返回的结果中容器 ID 只有上面返回字符串的前面一部分,这个往往是我们会用的容器 ID
要怎样才能控制它的 shell 呢?
又要接触新的 docker 命令了
- attach
- exec
exec 需要加上 -i
和 -t
参数以及命令,比如 /bin/bash
.
所以执行格式是这样的
|
|
然后我们需要执行 bash
|
|
很快,我们就进入了容器的 shell.
我们可以用 cat /etc/os-release
来查看系统信息.
我们可以很清晰的看到,上面返回的是 Ubuntu 而我用的是 Arch, 因此我们可以确定容器里的东西不会影响到操作系统.
什么?不清晰?那再看清楚一点吧
|
|
退出还是一样的可以用 exit
, 但是此时的 exit 只是退出这个 bash, 它并不会关闭容器.
执行 docker ps
我们可以看到它还在运行.
那么我们接下来试试 attach
它的用法是
|
|
所以我需要执行
|
|
这样一来我们也可以得到一个shell,但是如果我们执行了 exit
, 这个容器是会被停止的.
来试试看?
很明显,当 exit
被执行之后用 docker ps
命令看不到正在运行的容器ID,这说明容器被停止了.
如果需要再次启动这个容器呢,我们可以使用 start 或者 restart 命令来重启.
|
|
此时我们用 docker ps
就又能看到它在运行了
使用 docker ps -a
命令可以查看所有的容器,无论是否正在运行
|
|
删除容器
如果这些容器不需要了怎么办,
比如玩坏了,要把它删掉
那就要用 docker rm
命令
|
|
后面接上容器 ID 就能删除, 可以删除多个
|
|
然后在用 docker ps -a
来查看, 就看不到任何容器 ID 了
镜像
docker 容器运行的前提条件是它需要相应的镜像.
可以用 docker images
来查看本地已经有的镜像, 如果需要的别的镜像可以用 docker pull
来获取
|
|
我们来获取 php 的镜像
|
|
等待他们自动下载完成,镜像就可以用了.
如果你运行容器的时候没有事先拉取镜像的话, docker 则会在运行容器的时候临时进行拉取.
下载进程完成之后, 我们查看一下现有的镜像
|
|
|
|
-
REPOSITORY:表示镜像的仓库源
-
TAG:镜像的标签
-
IMAGE ID:镜像ID
-
CREATED:镜像创建时间
-
SIZE:镜像大小
同一仓库源可以有多个 TAG,代表这个仓库源的不同个版本,如 ubuntu 仓库源里,有 15.10
、14.04
等多个不同的版本,我们使用 REPOSITORY:TAG
来定义不同的镜像。
删除镜像
当然, 不需要的镜像也是可以删除的.
|
|
如图,这样就把不需要的镜像删除了
dockerfile
啥是 dockerfile? Dockerfile 是用来构建镜像文件的文本文件, 文件里面包含的是一条条指令和说明, 和一些 shell 脚本类似(比如 PKGBUILD )
而一个简单的 Dockerfile 是长这样的
|
|
FROM
定制的镜像都是基于 FROM 的镜像, 这里的 nginx 就是定制需要的基础镜像。后续的操作都是基于 nginx。RUN
用于执行后面跟着的命令行命令。有以下俩种格式:
shell 格式:
|
|
exec 格式:
|
|
熟悉 Linux 操作的话, 上手这玩意也就很简单了, 但是值得注意的是菜鸟教程当中说的这一段:
Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。例如:
|
|
以上执行会创建 3 层镜像。可简化为以下格式:
|
|
也就是说我们要尽量在 RUN 当中写命令脚本的时候尽量写并列语句.
一个简单的 Web 服务器.
现在我想试试用 docker 来跑一个简单的网页了.
就跑一下我之前闲着没事干写的登录页面吧.
首先我们要创建一个目录
|
|
先把前端的静态文件复制进去
|
|
然后进入该目录
|
|
检查一下文件
|
|
|
|
ok ,现在我们来写一个 dockerfile
|
|
- COPY
复制指令,从上下文目录中复制文件或者目录到容器里指定路径。
格式:
|
|
[--chown=<user>:<group>]
:可选参数,用户改变复制到容器内文件的拥有者和属组。
<源路径>
:源文件或者源目录,这里可以是通配符表达式,其通配符规则要满足 Go 的 filepath.Match 规则。例如:
|
|
<目标路径>
:容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。
我的思路和正常的搭建方式一样,安装 nginx 之后再把写好的静态文件复制到web根目录就行, 但是用 docker 的效率高很多.
但是如果不用 docker 的话, 我至少要多花半个小时的时间去配置一个虚拟机, 配置软件源 安装 nginx 什么的, 花的时间就更多了, 而现在我只需要写一个脚本就能一键部署, 而且还能保存为镜像分享给别人,一劳永逸~
好了, 话不多说, 开始构建镜像
使用 docker build
命令通过目录下的 dockerfile
文件构建一个镜像,
-t
的属性值是指 <镜像名称:镜像标签>
|
|
注意了, 我在最后面还加了一个 .
, 这个叫做上写文路径, 也是指相对路径
然后我们查看一下镜像列表
|
|
很明显,我们可以看到我们刚刚创建的镜像, 镜像 ID 是 9acd8c30bd5b
.
那么接下来把它部署到容器里~ 用 -p
来指定端口绑定 <外部端口:内部端口>
|
|
现在我们已经把容器的 80 端口映射到了宿主机的 8080 端口~
然后访问我们的本地 IP + 8080 就可以访问到那个页面了, 我这里用 127.0.0.1:8080
访问
成功访问!
这样一来,快速部署 nginx 就完成了!
结语
经过对 docker 初学习和初体验, 我也浅尝到了它的高效率和便捷性, 收获还是比较多的.
但目前还是一个入门的阶段,更多高级应用方法还等着去探索~
诶? 你问我难不难? QwQ ~
对 Linux 熟悉的人来玩这个没几天应该就能玩会了, 不过要做到深入的了解还是需要时间的.
那 就这样吧