前言:为什么要 docker?
- 更高效的利用系统资源
- 更快速的启动时间
- 一致的运行环境
- 持续交付和部署
对比虚拟机
| 特性 | 容器 | 虚拟机 |
|---|---|---|
| 启动 | 秒级 | 分钟级 |
| 硬盘使用 | 一般为 MB | 一般为 GB |
| 性能 | 接近原生 | 弱于 |
| 系统支持量 | 单机支持上千个容器 | 一般几十个 |
几个基本概念
镜像(Image)
镜像是一个虚拟的概念,相当于一个 root 文件系统。提供了容器运行时所需的程序、库、资源、配置文件以及运行时所需要的配置参数等内容。应用程序及其依赖,都打包在 Image 中,通过这个文件,才能生成 Docker 容器。
容器(Container)
镜像和容器,类似面向对象的 类 和 实例。容器就类似于实例。容器是镜像运行起来的实体,可以被创建、启动、停止、删除等操作。
仓库(Registry)
保存镜像的地方。Docker Hub。一个 Docker Registry 中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。
例如想要使用 MySQL ,按照官方文档指令,docker pull mysql 即可。
正文
食用前提:
- 已经安装好 docker。安装文档。
- 最好配置了镜像加速(可选)。因为国内访问 Docker 镜像,速度都比较慢,为了更快访问 Docker 镜像,可以配置第三方加速器如:网易、USTC、阿里云。镜像加速配置方式。链接文章拉到底部,对 Windows 和 macOS 都有配置教程。
获取镜像
用法:
docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]
我们拿 nginx 举例,获取最新的 nginx 镜像
$ docker pull nginx
latest: Pulling from library/nginx
54fec2fa59d0: Pull complete
4ede6f09aefe: Pull complete
f9dc69acb465: Pull complete
Digest: sha256:86ae264c3f4acb99b2dee4d0098c40cb8c46dcf9e1148f05d3a51c4df6758c12
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
查看该镜像是否已经成功 pull
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 602e111c06b6 4 days ago 127MB
有如上信息输出,说明 TAG 为 latest 的 nginx 已经成功 pull
还有其他 版本 的 nginx 可供使用, dockerhub 地址
运行容器
有了镜像之后,我们能以镜像为基础,创建出相应的容器。以上一步获取的 nginx 为例,最简单的执行,按照上一步获取的 IMAGE ID,执行 docker run
$ docker run 602e111c06b6
此时拥有 nginx 配置环境的容器即被启动了,打开另一个 tab ,查看该容器的运行状态:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c76674325dc9 602e111c06b6 "nginx -g 'daemon of…" 2 minutes ago Up 2 minutes 80/tcp
可以看到这个 container 的状态(STATUS)为「Up 2 minutes」。根据 IMAGE ID,可以知道这是上一步启动的 nginx image.
接下来进一步在本地电脑上展示我们跑起来的容器(也就是外部访问容器的实现)------对容器进行端口映射:
在 docker run 时候通过 -p 或 -P 参数来启用
$ docker run -p 8082:80 602e111c06b6
http://localhost:8082/ 就可以访问到我们跑起来的 nginx 内容了。
还可以给跑起来的容器命名,参数:--name
$ docker run -p 8082:80 --name test-nginx 602e111c06b6
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f0bbe4ccbc97 602e111c06b6 "nginx -g 'daemon of…" 7 seconds ago Up 5 seconds 0.0.0.0:8082->80/tcp test-nginx
使用 Dockerfile 定制镜像
DOckerfile 就是一个文本文件,用来构建一个镜像,文本内容包含了一条条用来构建镜像所需要的指令和说明。
Dockerfile 的指令有:
- COPY:从上下文目录中复制文件或者目录到容器里指定路径
- ADD
- CMD:类似于 RUN 指令,用于运行程序
- ENV:设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量
- EXPOSE:声明端口
- FROM:定制需要的基础镜像
- LABEL
- STOPSIGNAL
- USER:指定执行后续命令的用户和用户组,这边只是切换后续命令执行的用户
- VOLUME:定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。
- WORKDIR:指定工作目录
- ONBUILD (when combined with one of the supported instructions above)
其他更详细的解释,见官方文档。
踩坑:创建 Dockerfile 建议不要用图形化创建,避免存在隐形的后缀。文件名字即为 Dockerfile,无后缀。
例子一
创建一个最简单的 Dockerfile,达到的效果是,在构建镜像时输出一段文字
⋊> ~/Desktop mkdir test-docker-file 14:15:15
⋊> ~/Desktop cd test-docker-file/ 14:15:29
⋊> ~/D/test-docker-file touch Dockerfile 14:15:36
⋊> ~/D/test-docker-file vi Dockerfile
编辑 Dockerfile 的内容是:
FROM nginx
RUN echo '这是一个本地构建的nginx镜像'
退出 vim 编辑,然后执行:
⋊> ~/D/test-docker-file docker build -t test-docker-file .
Sending build context to Docker daemon 2.048kB
Step 1/2 : FROM nginx
---> 602e111c06b6
Step 2/2 : RUN echo '这是一个本地构建的nginx镜像'
---> Running in e3bdfe16c57b
这是一个本地构建的nginx镜像
Removing intermediate container e3bdfe16c57b
---> 06c60b75a00c
Successfully built 06c60b75a00c
Successfully tagged test-docker-file:latest
如我们所料,第二步输出了 “这是一个本地构建的nginx镜像”
例子二:为一个 Web 程序定制镜像
首先,我们准备一个 vue 项目,脚手架一把嗦一个:
⋊> ~/D/test-docker-file cd ../ 14:22:10
⋊> ~/Desktop vue create test-docker
// 创建成功之后
⋊> ~/Desktop cd test-docker 14:28:40
⋊> ~/D/test-docker on master npm run serve 14:29:01
// 在 8080 端口访问项目正常,还是熟悉的 vue 主页
接下来编写 Dockerfile,对该项目进行定制,我们想要实现的效果:
- 定制一个镜像
- 跑起来后,能从容器外部访问该程序
创建一个.dockerignore 文件,避免镜像中存在太多多余的文件,类似 .gitignore。文件内容:
./node_modules
Dockerfile 内容如下:
FROM node
WORKDIR /app
COPY . /app/
RUN npm install -g cnpm --registry=https://registry.npm.taobao.org
RUN cnpm install
EXPOSE 8080
CMD [ "npm", "run", "serve" ]
解释:
- 拉取基础镜像 node
- 创建工作目录 /app
- 将当前的上下文拷贝进工作目录 /app
- 更换 npm 源头为淘宝源
- 执行
npm install - 暴露 80 端口供容器外部访问
- 在 docker run 的时候执行
"npm run serve"
执行:
docker build -t test-docker-vue .
运行过程:
⋊> ~/D/test-docker on master ⨯ docker build -t test-docker-vue . 14:52:00
Sending build context to Docker daemon 808.4kB
Step 1/7 : FROM node
// 省略
Removing intermediate container 5662dc5aae9e
---> 42894d24de49
Step 6/7 : EXPOSE 80
---> Running in 3f3524d92c02
Removing intermediate container 3f3524d92c02
---> 8b37aa222f33
Step 7/7 : CMD [ "npm", "run", "serve" ]
---> Running in eeee0de97656
Removing intermediate container eeee0de97656
---> 94275461b4d8
Successfully built 94275461b4d8
Successfully tagged test-docker-vue:latest
如上,我们成功的构建了一个镜像,id 为 94275461b4d8,tagged 为 test-docker-vue:latest。
命令行查看当前所有的 image:
docker image ls
可以看到存在一条数据:
REPOSITORY TAG IMAGE ID CREATED SIZE
test-docker-vue latest 94275461b4d8 26 minutes ago 1.2GB
将这个 image 跑起来,并将本地的 8083 端口映射至容器的 8080 端口:
docker run -p 8083:8080 94275461b4d8
等待运行结果。
代码全部上传至 GitHub,传送门