什么是 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 引擎
  1. 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
  1. 必须开启 centos-extras 存储库(默认开启)
  2. 卸载旧版本 Docker
$ sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
  1. 安装 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
    
    # 阿里源,国内速度快
  1. 安装
    Docker 分社区版和企业版,个人学习使用社区版 docker-ce
$ sudo yum install docker-ce docker-ce-cli containerd.io
  1. 启动 Docker
$ sudo systemctl start docker
  1. 查看版本
$ 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 常用命令

镜像命令

  1. 获取镜像
$ 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
  1. 查看本地镜像
$ 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
  1. 删除镜像
$ docker rmi 镜像ID

$ docker rmi 1b0fd4cb2c2d
Deleted: sha256:1b0fd4cb2c2d4bbe36e3a686241e3357a60ffd18d7dbe0f3569df337ec6c1312
Deleted: sha256:1070c7d55ddbef6b9473997042aa02e9799c4b02e2b9aad9cbb670c0871d3460
Deleted: sha256:4cc41c00a2b3ada1f8cf1b1423296d65687720a39998e48e78a0debe26ae3125
Deleted: sha256:2af4642b6ff14bab31c288dacf4a2be8d1ca437d4d68023d315475dde67dba42
Deleted: sha256:a274573eada07496d8be6d0e058d5675615398e3089fc8f2171356ecd27f8b07
Deleted: sha256:427eea41be28f7c846a23c6c170bacda9349b28db9d189dd72dec4496eabe5ca

容器命令

  1. 运行镜像/创建容器
$ 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 退出
  1. 查看容器
$ 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
  1. 操作容器
// 启动容器
$ 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 服务

注意事项:

  1. 千万不要忘记编写 .dockerignore 文件
.git/
node_modules/
  1. Docker镜像是一层一层的构建的,将多个 RUN 指令合并为一个