什么是 Docker
Docker 是一种运行于 Linux 和 Windows 上的软件,用于创建、管理和编排容器的虚拟化技术。
Docker 引擎是用于运行和编排容器的基础设施工具。
什么是容器技术
容器技术是一种类似虚拟机技术,但又有明显优势的技术。容器分 Linux 容器和 Windows 容器。
容器模型跟虚拟机模型相似,其主要的区别在于,容器的运行不会独占操作系统。实际上,运行在相同宿主机上的容器是共享一个操作系统的,这样就能够节省大量的系统资源,如 CPU、RAM 以及存储。
Docker 可以干什么
Docker 作为一个软件集装箱化平台,可以让开发者构建应用程序时,将它与其依赖环境一起打包到一个容器中,然后很容易地发布和应用到任意平台中。
Docker基本概念
镜像(Image)
Docker 镜像(Image),就相当于是一个 目标文件系统,通过镜像可以构建出对应目标的服务。比如可以利用nodejs的镜像构建出node服务的容器。
容器(Container)
镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
仓库(Repository)
仓库就是存放镜像的地方,仓库分为公有仓库和私有仓库(类似 git )。
Docker 安装
https://docs.docker.com/get-docker/
根据自己系统安装对应的 Docker 。
在CentOS上安装 Docker 引擎
- CentOs 版本需要在 7 以上 或 内核版本高于 3.10
// 查看版本
$ lsb_release -a
LSB Version: :core-4.1-amd64:core-4.1-noarch
Distributor ID: CentOS
Description: CentOS Linux release 7.8.2003 (Core)
Release: 7.8.2003
Codename: Core
// 查看内核
$ uname -a
3.10.0-693.2.2.el7.x86_64 #1 SMP Tue Sep 12 22:26:13 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
- 必须开启 centos-extras 存储库(默认开启)
- 卸载旧版本 Docker
$ sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
- 安装 yum-utils 软件包并设置稳定的存储库
$ sudo yum install -y yum-utils
$ sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
# 官方源,速度慢,需要代理
$ sudo yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 阿里源,国内速度快
- 安装
Docker 分社区版和企业版,个人学习使用社区版 docker-ce
$ sudo yum install docker-ce docker-ce-cli containerd.io
- 启动 Docker
$ sudo systemctl start docker
- 查看版本
$ docker -v
Docker version 19.03.12, build 48a66213fe
设置淘宝镜像加速
获取加速地址:
https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://XXX.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
Docker 常用命令
镜像命令
- 获取镜像
$ docker pull 镜像名:版本号
docker pull node:12.18.2-alpine3.12
12.18.2-alpine3.12: Pulling from library/node
df20fa9351a1: Pull complete
4b13f99ed176: Pull complete
7cb2200a4599: Pull complete
86835664906f: Pull complete
Digest: sha256:613a7e4ab09792e7f779cdcf93d088823f33a21440822a17fa1331281cf51f67
Status: Downloaded newer image for node:12.18.2-alpine3.12
docker.io/library/node:12.18.2-alpine3.12
- 查看本地镜像
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql 5.6 1d3d3845393d 11 days ago 302MB
node 12.18.2-alpine3.12 2b682ee03053 6 weeks ago 89.7MB
node 10.22.0-alpine3.11 8e473595b853 3 weeks ago 83.5MB
<none> <none> e11a63072a39 10 days ago 354MB
- 删除镜像
$ docker rmi 镜像ID
$ docker rmi 1b0fd4cb2c2d
Deleted: sha256:1b0fd4cb2c2d4bbe36e3a686241e3357a60ffd18d7dbe0f3569df337ec6c1312
Deleted: sha256:1070c7d55ddbef6b9473997042aa02e9799c4b02e2b9aad9cbb670c0871d3460
Deleted: sha256:4cc41c00a2b3ada1f8cf1b1423296d65687720a39998e48e78a0debe26ae3125
Deleted: sha256:2af4642b6ff14bab31c288dacf4a2be8d1ca437d4d68023d315475dde67dba42
Deleted: sha256:a274573eada07496d8be6d0e058d5675615398e3089fc8f2171356ecd27f8b07
Deleted: sha256:427eea41be28f7c846a23c6c170bacda9349b28db9d189dd72dec4496eabe5ca
容器命令
- 运行镜像/创建容器
$ docker run -d 镜像名/镜像ID // 以【后台运行】方式启动镜像,常用方式
$ docker run -d 8e473595b853
ec8449bf6ef8c25003cd8c9d22214d87d02cd4bd3ff24fd91d8c32ffa0b37ee3
// 因为没有任务,执行后又关闭了
$ docker run -it 镜像名/镜像ID // 以【交互式】方式启动镜像
$ docker run -it 8e473595b853
// 8e473595b853 是 node:10.22.0-alpine3.11 的镜像ID
// 启动结果如下,进入命令行交互启动
> let a = 3;
undefined
> console.log(a)
3
undefined
>
>
(To exit, press ^C again or type .exit)
>
// 连续两次按 ^C 退出
- 查看容器
$ docker ps -a // 查看所有容器
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ec8449bf6ef8 8e473595b853 "docker-entrypoint.s…" About a minute ago Exited (0) About a minute ago recursing_elgamal
2bb00ce64887 8e473595b853 "docker-entrypoint.s…" 7 minutes ago Exited (0) 2 minutes ago hardcore_panini
07d4ffb05262 blog_nodejs "docker-entrypoint.s…" 10 days ago Up 28 minutes 0.0.0.0:3000->3000/tcp nodejs
5732fae3140f blog_blog_mysql "docker-entrypoint.s…" 10 days ago Up 28 minutes 3306/tcp, 0.0.0.0:3307->3307/tcp blog_mysql
$ docker ps // 查看正在运行的容器
07d4ffb05262 blog_nodejs "docker-entrypoint.s…" 10 days ago Up 31 minutes 0.0.0.0:3000->3000/tcp nodejs
5732fae3140f blog_blog_mysql "docker-entrypoint.s…" 10 days ago Up 31 minutes 3306/tcp, 0.0.0.0:3307->3307/tcp blog_mysql
- 操作容器
// 启动容器
$ docker start 容器id
// 停止容器
$ docker stop 容器id
$ docker stop 5732fae3140f
5732fae3140f
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
07d4ffb05262 blog_nodejs "docker-entrypoint.s…" 10 days ago Up 34 minutes 0.0.0.0:3000->3000/tcp nodejs
// 进入容器
$ docker attach 容器id
// 删除容器
$ docker rm 容器id
// 删除一起需要停止容器
$ docker rm 07d4ffb05262
Error response from daemon: You cannot remove a running container 07d4ffb052628a429efbb59239e2a26791af5dd7999cb17d8559a37418ef4929. Stop the container before attempting removal or force remove
$ docker stop 07d4ffb05262
07d4ffb05262
$ docker rm 07d4ffb05262
07d4ffb05262
Dockerfile
一般了解上节中的这些常用命令即可满足我们日常工作了,毕竟我们是开发,不是专业做运维的。但是在一般项目当中,我们不会直接在命令行里直接操作docker,而是会使用DockerFlie来构建自己的项目镜像。
什么是 Dockerfile
Dockerfile 是一个 Docker 镜像的描述文件,包含了一条条的指令,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。我们可以使用 Dockerfile 构建自己的镜像。
Dockerflie 指令
FROM # 基础镜像,一切都从这里开始构建
MAINTAINER # 维护者信息
WORKDIR # 设置当前工作目录
ENV # 设置环境变量
RUN # 构建镜像需要执行的命令
ADD # 添加内容
COPY # 将文件拷贝到镜像中
VOLUME # 设置容器卷
EXPOSE # 设置暴露端口
CMD # 指定容器启动的时候要运行的命令 两者区别如下链接
ENTRYPOINT #
怎么写 Dockerfile
如何编写最佳的Dockerfile:
- 编写.dockerignore 文件
- 容器只运行单个应用
- 将多个 RUN 指令合并为一个
- 基础镜像的标签不要用 latest
- 每个 RUN 指令后删除多余文件
- 选择合适的基础镜像(alpine 版本最好)
- 设置 WORKDIR 和 CMD
- 使用 ENTRYPOINT (可选)
- 在 entrypoint 脚本中使用 exec
- COPY 与 ADD 优先使用前者
- 合理调整 COPY 与 RUN 的顺序
- 设置默认的环境变量,映射端口和数据卷
- 使用 LABEL 设置镜像元数据
- 添加 HEALTHCHECK
举个例子
在 project_name 目录下 创建 Dockerfile 文件,project_name 就是前端项目的根目录名。
FROM node:12.18.2-alpine3.12 # 获取合适的基础镜像(alpine 版本最好)
ENV PROJECT_DIR=/project_name # 指定工作目录变量
WORKDIR $PROJECT_DIR # 使用变量 指定工作目录
COPY package* $PROJECT_DIR/ # 将 package.json 和 package-lock.json 文件拷贝进镜像
RUN npm config set registry http://registry.npm.taobao.org \ # 设置 npm 淘宝镜像
&& npm install # 安装依赖
COPY . $PROJECT_DIR # 复制项目文件到工作目录
RUN npm run build # 执行构建任务
EXPOSE 80 # 暴露到宿主机端口号
CMD [ "node", "dist/main" ] # 运行 node 服务
注意事项:
- 千万不要忘记编写 .dockerignore 文件
.git/
node_modules/
- Docker镜像是一层一层的构建的,将多个 RUN 指令合并为一个