如果没有docker,我们需要手动在一台机器上安装数据库,配置nginx,然后还要做不同机器操作系统差异的适配。有了docker,我们可以把开发、测试环境,一键部署到任何一台机器上。只要该机器安装了Docker 。
Docker就是一种虚拟机技术,比传统虚拟机(如vmware、virtualbox)要更加简单、轻量。

  • 启动快
  • 资源占用少
  • 体积小

    安装

    https://docs.docker.com/desktop/install/mac-install/
    安装完记得镜像加速,搜索”docker 镜像加速“即可。
    安装完,运行docker version可查看版本。

    相关文档

    docker cli

    术语

    image.png

  • Dockerfile构建出镜像,镜像推送到镜像仓库

  • 从 仓库下载镜像
  • 镜像启动容器,一个镜像可以启动多个容器。容器就是虚拟机的能力。

    常用命令

    image镜像

  • 下载镜像 docker pull :

  • 查看所有镜像 docker images
  • 删除镜像 docker rmi
  • 上传镜像 docker push /: ,要先注册https://hub.docker.com/

如果 docker images出现REPOSITORY是的情况,可以运行 docker image prune 删除。

container容器

容器是有能力的,比如nginx容器。可以看做最小型的一个操作系统

  • 启动容器

    1. docker run -p xxxx:xxxx -v=hostPath:containerPath -d --name <container-name><image-name>
    • -p 端口映射 :本地和容器端口的映射
    • -v 数据卷,文件映射
    • -d 后台运行
    • —name 定义容器名称 镜像的名称
  • 查看所有容器 docker ps ,加-a显示隐藏的容器
  • 停止容器 docker stop
  • 删除容器 docker rm ,加-f是强制删除
  • 查看容器信息,如IP地址 docker inspect
  • 查看容器日志 docker logs
  • 进入容器控制台 docker exec -it /bin/sh

    创建容器

    基于 nginx 镜像创建一个最简单的容器:启动一个最简单的 http 服务
    使用 docker run 来启动容器,docker ps 查看容器启动状态。

    1. docker run -d --name nginx -p 8888:80 nginx:alpine

    其中:

  • -d: 启动一个 daemon 进程

  • —name: 为容器指定名称
  • -p host-port:container-port: 宿主机与容器端口映射,方便容器对外提供服务
  • nginx:alpine: 基于该镜像创建容器

此时在宿主机使用 curl 测试容器提供的服务是否正常

仅仅让nginx做为静态服务

单独演示一下 -v 数据卷。

  1. # 1. 新建 /Users/wfp/html/index.html ,内容自定义即可
  2. # 让nginx服务指向外面(docker外面)的文件
  3. # 2. 运行
  4. docker run -p 81:80 -v=/Users/wfp/html:/usr/share/nginx/html -d --name nginx1 nginx
  5. # 3. 访问 重新访问 localhost:81 ,看是否你创建的页面?


Dockerfile

在使用 docker 部署自己应用时,往往需要自己构建镜像。docker 使用 Dockerfile 作为配置文件构建镜像,
注意∶必须是 Dockerfile 这个文件名,必须在项目的根目录
简单看一个 node 应用构建的Dockerfile
1、编写Dockerfile

  1. # 基于一个旧有的镜像,格式: FROM <image> [AS <name>]
  2. FROM node:alpine
  3. # 把目录,或者 url 地址文件加入到镜像的文件系统中
  4. ADD package.json package-lock.json /code/
  5. WORKDIR /code
  6. # 设置时区
  7. RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
  8. # 构建镜像时,一般用于做一些系统配置,安装必备的软件。可有多个 RUN
  9. # 安装
  10. RUN npm set registry https://registry.npm.taobao.org
  11. RUN npm install
  12. RUN npm install pm2 -g
  13. ADD . /code
  14. # 启动容器时,只能有一个 CMD
  15. CMD echo $SERVER_NAME && echo $AUTHOR_NAME &&npm run server && npx pm2 log #一定要是阻塞控制台的程序
  16. # 环境变量
  17. ENV SERVER_NAME="tanchidemao"
  18. ENV AUTHOR_NAME="roy"
  • Dockerfile描述了镜像如何构建和启动,应该要把一些麻烦的操作放在构建镜像的阶段去操作,然后在启动容器时,就会比较快。因为构建一般只有一次,启动是有多次的。
  • 注意CMD后面一定要是能阻塞控制台的程序
  • 本地安装pm2 npm i pm2 --save-dev,或者Dockerfile中全局安装pm2
  • 由于 Docker 容器中没有数据库环境,服务启动不会成功

可以临时修改一下,再测试:

  • 去掉数据库连接
  • 去掉 bin/www 数据同步
  • Dockerfile

2、**.dockerignore**文件忽略

  1. .git
  2. node_modules
  3. logs
  4. .docker-volumes
  5. wfp_test


3、构建镜像并启动容器

  1. docker build -t editor-server . # 构建 image
  2. docker images
  3. docker run -p 8081:3000 -d --name server1 editor-server # 创建容器,注意端口映射
  4. docker ps
  5. docker logs <container-id> # 需等待构建完成
  6. # 访问 localhost:8081 ,查看 docker logs
  7. docker stop <container-id>
  8. docker rm <container-id>
  9. docker rmi <image-id>
  • 关于端口映射:单独用docker run 启动某个服务就需要进行端口映射。如果用docker-compose启动就不用,因为端口映射等相关参数已经写在配置文件里面了,所以其实用docker-compose up 比较方便

4、访问[http://0.0.0.0:8081/](http://0.0.0.0:8081/),查看日志:docker logs editor-server

多阶段构建

理解:这里最后生成的镜像以最后一个 FROM 为准,之前的会被抛弃。
image.png

底层原理

docker 底层使用了一些 linux 内核的特性,大概有 namespace,cgroups 和 ufs。

1、docker 使用 linux namespace 构建隔离的环境

它由以下 namespace 组成

  • pid: 隔离进程
  • net: 隔离网络
  • ipc: 隔离 IPC
  • mnt: 隔离文件系统挂载
  • uts: 隔离hostname
  • user: 隔离uid/gid

    2、使用control groups限制资源

    比如某个容器只能使用 100M 内存

    3、使用Union file systems进行分层

    UnionFS 是一种分层、轻量级并且高性能的文件系统,支持对文件系统的修改作为一次提交来一层层的叠加。docker 的镜像与容器就是分层存储,可用的存储引擎有 aufs,overlay 等。
    关于分层存储的详细内容可以查看官方文档 docker: About storage drivers