上篇在这里 docker 入门上篇
本文主要记录:
- 创建 docker 镜像
- docker-compose 的使用
创建镜像
我们开始使用的镜像都是别人制作好的,这些镜像可以用来创建多个不同的实例容器,但是不可以修改镜像本身,所以当我们想去定制自己的镜像时,需要自己创建一个新的镜像。创建镜像的方式有两种。
使用容器制作镜像
前面说到镜像本身是不可以修改的,所以没办法直接在镜像上做定制,但是容器是可以修改的,我们可以在容器上做一些自己需要的定制,然后再将容器反转为镜像,这种操作是可以的,用一张图表示:

要注意的是,容器反转成的镜像并不是覆盖源镜像,而是创建了一个新的镜像(不要被图误导)。
来查看下当前本地的镜像:

现在我们就来定制一个 centos 的镜像,首先创建一个新容器:
docker run -it --name=aa centos /bin/bash
创建完成进入容器,我们要拿这个容器生成一个镜像,为了与源镜像区分开,所以我们来做一点定制,只是简单示范下,比如发现容器里默认没有 vim 工具,所以使用 yum install vim 来安装一下 vim:

安装完 vim 也相当于做了一个小定制,现在就将容器转换为镜像,使用命令:
docker commit 容器ID 镜像名称:版本号
操作如下:

如图,拿到容器的 id 后即可创建新的镜像。有个小细节就是当我们使用容器 id 时,可以不用输入完整的 id,只要前几位就行了。现在我们创建好了新的镜像 my_centos,为了验证可用性,我们用它来创建一个新的容器:
docker run -it --name=bb my_centos:1.0 /bin/bash
创建完成后使用 docker ps 来验证:

可以看到 bb 容器已经存在,而且先前的 aa 容器已经不在了,这说明当容器转换为镜像后,容器本身将删除。
另外,还记得我们之前在 aa 容器上做的定制嘛,我们安装了 vim 工具,现在我们在 bb 容器上使用 vim 命令后,发现是有这个工具的。

这说明定制生效。习惯用一张图来表示流程:

以上就是使用容器创建镜像的过程。
使用 Dockerfile 创建镜像
创建镜像最常用的方式就是使用 Dockerfile。Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。它的格式是这样的:
FROM scratch
ADD centos-7-x86_64-docker.tar.xz /
LABEL org.label-schema.schema-version="1.0" \
org.label-schema.name="CentOS Base Image" \
org.label-schema.vendor="CentOS" \
org.label-schema.license="GPLv2" \
org.label-schema.build-date="20191001"
CMD ["/bin/bash"]
这是 centos 镜像的 Dockerfile 文件,它有 4 条指令,关键词分别是:FROM、ADD、LABEL 和 CMD,每一条指令构建一层,每条指令后的内容就是描述该层应当如何构建。
Dockerfile 文件的指令有很多,推荐看菜鸟教程的文档,我主要来介绍一下使用 Dockerfile 的过程。
使用 Dockerfile 创建 centos 镜像
接下来我们使用 Dockerfile 方式来定制一个自己的 centos 镜像。
创建一个新目录,并在目录中新建 Dockerfile 文件:
// 目录名和文件名都随意
mkdir docker-files
cd docker-files
touch centos_dockerfile
在 centos_dockerfile 中输入以下内容并保存:
FROM centos:7
MAINTAINER aaa
RUN yum install -y vim
WORKDIR /root
CMD /bin/bash
来逐行解释一下这个 Dockerfile 文件:
FROM centos:7:表示基础镜像使用centos:7这个版本。如果本地已有这个镜像就直接使用,如果没有会先下载到本地;MAINTAINER aaa:作者名;RUN yum install -y vim:运行安装 vim 的命令,加上-y参数是因为安装vim过程中会有确认步骤;WORKDIR /root:设置工作目录,创建出来的容器进入时,默认所在的目录;CMD /bin/bash:启动容器时默认执行的命令。
用到的指令虽然不多,但已经够我们创建一个新的镜像了,在 docker-files 目录中执行命令:
docker build -f ./centos_dockerfile -t centos_with_vim:1 .
注意命令最后还有一个 .,它是上下文路径,是指 docker 在构建镜像,有时候想要使用到本机的文件(比如复制),docker build 命令得知这个路径后,会将路径下的所有内容打包。使用 . 就是将当前路径指定为上下文路径,一般不要放无用的东西在上下文路径中。
-f 参数后面接的是 Dockerfile 文件,-t 参数后面接的是要创建的镜像的名称或加上版本。
执行命令时:

可以看到会根据 Dockerfile 文件中的指令而一层层地去构建镜像,完成后使用 docker images 可以查看构建出来的镜像:

现在来使用这个新镜像去创建容器:
docker run -it --name=cc centos_with_vim:1 /bin/bash

创建完成进入容器后,首先验证了工作目录确实是 /root,然后 vim 工具也是存在的,这些都是我们在 Dockerfile 中配置好的,为了对比,可以直接创建一个基于 centos:7 源镜像的容器:

说明我们使用 Dockerfile 方式创建特定镜像成功。
使用 Dockerfile 创建 koa 项目镜像
拿个我们前端熟悉的东西来试试 Dockerfile,来创建一个 koa 项目的镜像。
首先我们要有一个koa项目,这个就做一个简单的demo就好了,比如我的:

app.js 内容:
const Koa = require('koa')
const app = new Koa()
app.use(async ctx => {
ctx.body = 'hello Docker!'
})
app.listen(3000)
package.json 内容:
{
"name": "koa-demo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node app.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"koa": "^2.11.0"
}
}
Dockerfile 就是之前说的配置文件,直接命名为 Dockerfile 时,就不需要加 -f 参数指定,它的内容是:
# 基础镜像指定为 node 镜像
FROM node:latest
# 指定作者信息,之前用的是 MAINTAINER,但推荐用 LABEL,格式 LABEL <key>=<value> ...
LABEL maintainer="pingzi"
# 移动当前目录下面的文件到app目录下
ADD . /app/
# 容器工作目录为 /app
WORKDIR /app
# 安装依赖
RUN npm install
# 暴露3000端口
EXPOSE 3000
# 执行 npm start
CMD ["npm", "start"]
还有一个 .dockerignore 文件,它的作用跟 .gitignore 类似,指定的内容就不会被打包到镜像中,这里在网上找的一份内容:
# Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules
jspm_packages
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history
.idea
.node_modules
node_modules
.vscode
好了齐活,现在来创建镜像,还记得创建镜像的命令吗?在当前目录下执行:
docker build -t koa_image .

有了镜像后,可以创建容器啦,执行:
docker run -d --name=koa_demo -p 9000:3000 koa_image
不出意外的话,此时在浏览器中就可以访问到啦~

到这,Dockerfile 的一些基本概念已经说完了,说的比较浅显,还需多实践啊~
docker-compose
docker-compose 是编排容器的工具,作用是可以使用一条命令来定义和运行多容器。
我们知道每当开启一个容器服务时,都需要执行 docker run 命令,这在服务少的时候是完全可行的,但是当一个业务需要很多的容器服务时,比如同时需要使用 node镜像,mysql镜像,nginx镜像和redis镜像等,此时你就得敲各个容器的启动参数,环境变量,容器命名等等一系列的操作,相当繁琐。而 docker-compose 的出现,就是解决了这一痛点,它通过一个配置文件来管理多个Docker容器,只需一个命令既可启动多容器服务。
安装 docker-compose
Linux 上安装:
sudo curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
添加可执行权限
sudo chmod +x /usr/local/bin/docker-compose
检查版本
docker-compose --version

另外,在 Mac 或者 Windows 上安装docekr客户端的,是默认包含Compose的,所以不需要单独安装。
简单试用 docker-compose
docker-compose 是通过配置文件来启动服务的,我们需要编写 docker-compose.yml 文件,这里我写了一个简单的例子:
version: '3'
services:
mongo:
image: mongo
restart: always
container_name: 'mongo-test'
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: example
ports:
- 27018:27017
volumes:
- /composetest/mongodb:/data/db
redis:
image: redis
container_name: 'redis-test'
ports:
- 6380:6379
创建一个新目录 /composetest(目录名字随意),然后在目录中创建 docker-compose.yml 文件,文件中输入上面内容,保存,注意缩进。
现在来看下这个文件描述了什么:
version:指定本 yml 依从的 compose 哪个版本制定的,这里是版本 3;services:指定多容器服务,这里指定了两个容器服务,分别是mongo和redis,注意这只是名字;image:指定容器运行的镜像,不指定版本时默认最新版;restart:重启容器,有4种情况- "no":是默认的重启策略,在任何情况下都不会重启容器
- always:容器总是重新启动
- on-failure:在容器非正常退出时(退出状态非0),才会重启容器
- unless-stopped:在容器退出时总是重启容器,但是不考虑在Docker守护进程启动时就已经停止了的容器;
container_name:指定自定义容器的名称,而不是随机生成的名称;environment:添加环境变量;ports:端口映射,宿主机端口 : 容器端口;volumes:数据卷挂载,宿主机目录 : 容器目录
总的来说,此描述文件定义了两个容器服务,一个是mongodb数据库的,一个是redis的,分别对应services下的mongo 和 redis,现在来运行这个文件,在这个文件所在的目录下运行:
docker-compose up

此时两个容器就被创建好了。可以看到有了 Compose 配置文件后,只需要一个命令即可创建并启动所有服务,极大简化了操作。在实际工作中,当需要多个容器相互配合来完成某项任务的时候,就应该考虑使用 docker-compose 了。
结尾
关于 docker的实践,还是很欠缺,我还学的动🤣,就这样吧~