来自:https://zhuanlan.zhihu.com/p/26517832?from_voters_page=true
dokcer是用Go语言开发的应用容器引擎,基于容器化,沙箱机制的应用部署技术,可适用于自动化测试、打包,持续集成和发布应用等场景。
docker基于容器化,沙箱机制,可使用较少的命令和脚本快速部署应用,一次构建,多处移植使用。再配合shell等脚本语言,可实现脚本化一键部署
docker 大部分都是依赖于命令执行的,简单易上手
docker现在已经成为比较受欢迎的serverless(无服务器架构)服务的基础架构。包括阿里云、亚马孙在内的云计算服务商都采用docker来打造serverless服务平台。
与此同时,基于docker的微服务架构也如火如茶的出现。
由此可见,docker容器技术非同一般
docker是沙箱机制,容器化部署技术,它主要作用在于通过运行容器来实现应用部署,而容器基于镜像运行。
简单的来说,将你的项目和依赖包(基础镜像)打成一个带有启动指令的项目镜像, 然后在服务器创建一个容器,让镜像在容器内运行,从而实现项目的部署。
服务器就是容器的宿主机,docker容器与宿主机是相互隔离的。
它不仅仅可以部署项目,还可以用于数据库的搭建,nginx服务搭建,nodejs、php等语言环境的搭建。
docker三个概念:镜像(Image)、容器(Container)、仓库(Repository)
同时还需要知道他们三个之前的关系。
docker镜像是使用Dokerfile脚本,将你的应用以及应用的依赖包构建而成的一个应用包,它通常带有改应用的启动命令。而这些命令会在容器启动的时候被执行,也就是说相应的应用再启动容器时被启动。
镜像的创建,需要通过配置Dockerfile脚本,然后执行dokcer build来创建。
举个例子:
docker build -t mydocker/node-server:v1
容器是使用 docker run --name 容器名 镜像 命令创建的,独立于宿主机(服务器)的沙箱,也可以理解为一个带有特殊结构的盒子,它在创建时会自动执行镜像自带的一些指令,从而实现应用的运行。
狭隘的将,容器的主要作用就在于给镜像提供运行空间和环境,并执行镜像的指令。
顾名思义,仓库是用来存东西的, 但不是用来存容器的,而是存储docker镜像。可以把docker镜像通过push命令推送到docker仓库,然后就可以在任何可以使用docker命令的地方通过pull命令把这个镜像拉取下来。
docker的使用方式主要有命令、Dockerfile脚本以及shell脚本三种。也就是说,可以把docker当作命令行工具来使用。
docker是沙箱机制,容器化部署技术,它主要作用在于通过运行容器来实现应用的部署,而容器则基于镜像运行。
因此,首先要有镜像,有了镜像才能基于镜像创建容器,才能把镜像存储在仓库。
于是可以这样去理解,镜像是基础,容器是镜像使用者,仓库是镜像的管理员。容器和仓库都是围绕着镜像来运作的,是对镜像的管理和使用。
另外,镜像、容器、仓库都有一套自己的docker命令,用于前期的构建以及后期的维护。
基本开发流程如下:
这个流程只开发一次,后期只做简单的维护就好。
经过上边的一系列描述,基本上大部分工作都是围绕镜像来做的,所以我们首先学习docker镜像。
docker有这么一种机制,在构建镜像时,可以依赖于一个父镜像作为底层镜像,与当前正要构建的镜像打包在一起,从而构成一个全新的镜像,而这个被作为依赖的父镜像,就是基础镜像。
比如,通常开发一个nodejs应用,它不是随处可运行的,它的运行需要依赖于操作系统环境和nodejs运行环境。
因此,一个node项目镜像是无法运行起来的,它需要依赖一个基础镜像,这个基础镜像就是nodejs镜像,nodejs镜像内包含了操作系统环境和nodejs环境。这样nodejs镜像+node项目构建出来的项目镜像才能完整的运行起来。
因此,在配置项目Dockerfile创建镜像脚本之前,需要先确立一个基础镜像。
基础镜像是如何使用的呢?主要是通过在Dockerfile脚本中使用From命令指定依赖一个父镜像(基础镜像)。
* 基础镜像通常不需要自己创建,dokcer官方有提供很多基础镜像供用户使用,比如nodejs镜像,java镜像,mongodb镜像,nginx镜像等等。
* 除了官方提供的,你还可以寻找第三方源提供的基础镜像。
docker镜像是通过配置Dockerfile脚本,然后执行docker build 命令来创建。
Dockerfile文件可通过nano Dockerfile命令或者touch Dockerfile命令来创建。
Dockerfile脚本文件通常放在项目的根目录下。也可以放在他文件,但执行docker build 时需要指定文件路径。
Dockerfile 语法由两部分构成,分别是注解和指令 + 参数
使用 “#” 可实现注释
Dockerfile 脚本通常分为以下四个部分:
下面直接来看个例子说明,这是我的开源博客后台sinn-server的Dockerfile脚本。
如下:
# 基础镜像信息
From registry.cn-hangzhou.aliyuncs.com/sessionboy/node:7.5
# 维护者信息
MAINTAINER sessionboy
# 镜像操作指令
COPY ./ /sinn-server
WORKDIR /sinn-server
RUN npm install
EXPOSE 8080
# 容器启动时执行的指令
ENTRYPOINT ["node","bin/run"]
Dockerfile有十几条命令可用于创建镜像,下面根据四个不同功能模块来介绍这些命令。
基础镜像信息只有一个From命令,指定依赖的基础镜像。
指定依赖的基础镜像,如果不存在就会从docker官方仓库寻找
# docker官方镜像仓库
# 指定docker官方仓库的新版nodejs镜像作为基础镜像
From node:latest
更多配置......
# 第三方镜像仓库,比如阿里云的 “https://dev.aliyun.com/search.html ”
# 指定标签为7.5的"registry.cn-hangzhou.aliyuncs.com/sessionboy/node"镜像作为基础镜像
From registry.cn-hangzhou.aliyuncs.com/sessionboy/node:7.5
更多配置……
维护者信息也只有一次MAINTAINER指令,用于描述该镜像的维护者信息
#MAINTAINER
MAINTAINER sessionboy [email protected]
镜像的操作指令有很多,逐一进行简单讲解。
CPOY指令用于拷贝宿主机的源目录/文件到容器内的某个目录,接受两个参数,原目录路径和容器内目录路径。
# 将“./”(当前目录)的文件拷贝到容器内的“/sinn-server” 目录
COPY ./ /sinne-server
功能和语法与COPY指令基本相同,不同在于使用ADD指令拷贝时,如果拷贝的是压缩文件,拷贝到容器中时会自动解压为目录
# 将当前的/server 目录拷贝到容器中的/project目录
ADD /server /project
指定RUN、CMD、ENTRYPOINT指令的工作目录
RUN是核心指令,它接受命令作为参数并用于创建镜像,。命令较多时可使用“\”换行
……
RUN ["/bin/bash", "-c", "echo hello"]
RUN rm ./tmp \
npm install
……
USER命令用于设置运行容器 UID
# 指定容器的UID为23541
USER 23541
VOLUME用于让你的容器访问宿主机上的目录。一般用来存放数据库和需要使用的数据。
# 指定容器可访问宿主机(服务器)的“/data”目录和“/home”目录
VOLUME ["/data",'"/home"]
配置当所创建的镜像作为其他新创建镜像的基础镜像时,所执行的操作指令。
ENV命令用于设置环境变量,在容器内被脚本或者程序调用。
# 设置环境变量 NODE_ENV 为 production
ENV NODE_ENV production
EXPOSE 用来指定端口,使容器内的应用可以通过端口和外界交互。
# 对外暴露8080端口
EXPOSE 8080
指定容器启动时执行的命令,每个Dockerfile只能有一条CMD命令,可被docker run提供的参数覆盖。
# 三种方式
CMD ["executable","param1","param2"] 使用 exec 执行,推荐方式
CMD command param1 param2 在 /bin/sh 中执行,提供给需要交互的应用
CMD ["param1","param2"] 提供给 ENTRYPOINT 的默认参数
容器启动后执行的命令,与CMD命令不同的是,它不会被docker run提供的参数覆盖。
# 两种方式
ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2(shell中执行)。
为了操作方便,docker提供了一套镜像的操作命令
镜像是基于Dockerfile脚本, 使用docker build 命令创建的,上面已经对Dockerfile做了详细的剖析,下面来说说如何使用Dockerfile脚本创建。
语法:
docker build [OPTIONS] PATH
OPTIONS作为对容器的配置项,内容有很多,可以到这里查看 Dockerbuild 命令, 一般不建议配置,使用默认的就好。
PATH为DockerFile脚本所在的目录,通常放在项目的根目录下,使用‘.’ 表示
-t标记用来添加tag,指定新的镜像信息,例如镜像名称,标签
# 使用当前目录的Dockerfile脚本创建名为“registry.cn-hangzhou.aliyuncs.com/sessionboy/sinn”的镜像,并标记为v1(标签,也可以理解为版本号)
docker build -t registry.cn-hangzhou.aliyuncs.com/sessionboy/sinn:v1 .
# 指定使用github.com/creack/docker-firefox的Dockerfile脚本创建镜像
docker build github.com/creack/docker-firefox
为了操纵方便,我们再根目录下建立一个名为build.sh 的shell脚本来执行这些命令,如下:
# build.sh
docker build -t registry.cn-hangzhou.aliyuncs.com/sessionboy/sinn:v1 .
sh build.sh 进行执行,看到Successfully,说明镜像已经创建成功。
使用命令docker images 可以查看本地所有的docker镜像
命令如下:
1.查看镜像:dokcer images
# 列出本地所有镜像
docker images
2.删除镜像:dokcer rmi 镜像
# 删除镜像
docker rmi registry.cn-hangzhou.aliyuncs.com/sessionboy/sinn
3.镜像重命名:dokcer tag 原镜像tag 新镜像tag
# 将镜像registry.cn-hangzhou.aliyuncs.com/sessionboy/sinn:v1重新标记为newImages:0.1
docker tag registry.cn-hangzhou.aliyuncs.com/sessionboy/sinn:v1 newImages:0.1
4.查看镜像创建历史:docker history 镜像
# 查看镜像registry.cn-hangzhou.aliyuncs.com/sessionboy/sinn的创建历史
docker history registry.cn-hangzhou.aliyuncs.com/sessionboy/sinn
5.镜像归档: docker save 镜像
# 将镜像registry.cn-hangzhou.aliyuncs.com/sessionboy/sinn保存成 sinn_v1.tar 归档文件
docker save -o sinn_v1.tar registry.cn-hangzhou.aliyuncs.com/sessionboy/sinn
6.基于归档文件创建镜像:dokcer import 归档文件 新镜像tag
docker import sinn_v1.tar new_sinn:v2
命令如下:
如果未指定镜像仓库地址,则默认官方仓库Docker Hub
# 登录到官方Docker Hub仓库
docker login -u 用户名 -p 密码
# 登录到阿里云docker仓库
docker login --username=用户名 registry.cn-hangzhou.aliyuncs.com
2.拉去镜像:docker pull 镜像
docker pull registry.cn-hangzhou.aliyuncs.com/sessionboy/sinn:v1
3.推送镜像:docker push 镜像
docker push registry.cn-hangzhou.aliyuncs.com/sessionboy/sinn:v1
4.搜索镜像:docker search 镜像
# 从官方Docker Hub仓库搜索node镜像
docker search node
镜像通过docker run命令使用的, 这是关于容器部分的操作
# 指定使用registry.cn-hangzhou.aliyuncs.com/sessionboy/sinn:v1镜像创建并启动容器
docker run --name sinn-server -p 8080:8080 registry.cn-hangzhou.aliyuncs.com/sessionboy/sinn:v1
创建容器的前提是要有镜像,有了镜像我们就可以创建和启动容器了。
通过docker run命令即可实现容器的创建,并也会启动容器,这个命令实际上就包含了创建和启动容器两部分工作。
因此,容器的创建和启动是一体的。
下面说说docker run命令的用法。
docker run 命令的用法如下:
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
或
dokcer run 容器配置项 镜像 额外的配置
OPTIONS 是一些给容器添加的配置项,比如指定容器的名称,IP,是否后台启动等等。
IMAGE则表示镜像。COMMAND 则是一些额外的命令。
OPTIONS具体配置项如下:
-a stdin: 指定标准输入输出内容类型,可选 STDIN/STDOUT/STDERR 三项;
-d: 后台运行容器,并返回容器ID。也可以理解为守护进程运行。
-i: 以交互模式运行容器,通常与 -t 同时使用;
-t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
--name="nginx-lb": 为容器指定一个名称;
--dns 8.8.8.8: 指定容器使用的DNS服务器,默认和宿主一致;
--dns-search example.com: 指定容器DNS搜索域名,默认和宿主一致;
-h "mars": 指定容器的hostname;
-e username="ritchie": 设置环境变量;
--env-file=[]: 从指定文件读入环境变量;
--cpuset="0-2" or --cpuset="0,1,2": 绑定容器到指定CPU运行;
-m :设置容器使用内存最大值;
--net="bridge": 指定容器的网络连接类型,支持 bridge/host/none/container四种类型;
--link=[]: 添加链接到另一个容器;
--expose=[]: 开放一个端口或一组端口;
--restart=no/on-failure/always 是否开机自动启动 ,no表示不启动,always表示始终启动,on-failure表示容器推出状态非0时重启
-v 标记来创建一个数据卷并挂载到容器里,实现宿主机目录或文件与指定的容器内目录或文件同步映射。
这么多配置项,除非有特殊需要,否则不必全部配置,使用docker默认的配置即可。但有些是经常使用或者必须的。比如:–name -d -v -e,这些是常用的配置项。
docker 提供了很多关于容器的操作命令,包括删除容器,停止、启动容器等等。
下面列出一些常用的操作容器的命令
1.查看容器:docker ps
#列出所有正在运行的容器
docker ps
2.启动已经停止的容器:docker start
# 启动一个获取多个已经被停止的容器
docker start [options] [containers]
3.停止容器:docker stop
# 停止正在运行的容器 sinn-server
docker stop sinn-server
4.重启容器:docker restart
# 重启正在运行的容器 sinn-server
docker restart sinn-server
5.删除容器:docker rm
# 删除容器 sinn-server
docker rm sinn-server
6.杀掉正在运行的容器(包括进程):docker kill
# 杀掉容器 sinn-server
docker kill sinn-server
7.进入容器:docker exec
这个命令比较重要,因为通常我们需要进入容器去操作一些东西。
docker exec -it 容器名称/ID 终端
# 例子:进入ID为0d15561b9f10的容器
docker exec -it sinn-server bash
或
docker exec -it 0d15561b9f10 /bin/bash
注意:进入容器后,如果想退出容器,只需要输入exit命令执行即可。
8.查看容器日志:dokcer logs
# 查看容器 sinn-server的日志
docker logs sinn-server
9.容器与主机之前数据拷贝:docker cp
往容器里拷贝数据,或从容器内拷贝数据出来,偶尔会常用到。
# 将主机的/data/user目录拷贝到容器sinn-server内的/data/user目录
docker cp /data/user sinn-server:/data/user
# 将容器sinn-server内的/data/user目录拷贝到主机的/data/user目录
docker cp sinn-server:/data/user /data/user
以往我们搭建数据库或nginx服务的时候,通常需要手动去安装,然后做大量的配置。期间也经常会遇到各种各样的问题。
下来介绍一下,如何使用linux服务器用docker来快速搭建一个mongodb数据库。
# 从docker官方仓库拉取mongo镜像(你也可以用第三方的mongo镜像,或自己创建的mongo镜像)
docker pull mongo
建立shell脚本“my-mongo.sh” 来运行mongodb容器启动命令
# my-mongo.sh
# 使用镜像"mongo"创建并启动容器"my-mongo"
docker run --name my-mongo -d -p 27017:27017 -v data/sinn-db:/data/db mongo
# -p 27017:27017 容器内27017端口与主机27017端口形成映射
# -d 守护进程运行
# --name my-mongo 指定容器名为my-mongo
# -v data/sinn-db:/data/db 将主机的"/data/sinn-db"目录挂载到容器内"/data/db"目录,作为mongodb数据存储目录
执行my-mongo.sh脚本即可
sh my-mongo.sh
容器启动成功后,mongodb已经启动。访问访问你IP的27017端口看到下面的提示,说明mongodb已经搭建成功。
It looks like you are trying to access MongoDB over HTTP on the native driver port.
使用docker搭建nginx也十分简单,只需要拉取nginx镜像,然后基于nginx镜像启动容器,启动时加一些nginx配置或指定nginx配置文件即可。
dokcer很强大,除了部署项目外,还可以用于搭建数据库,nginx服务等,它的用途十分广泛而且强大,另外它的性能消耗也很低,操作十分简单。
docker很容易学,它主要基于命令来操作,熟知这些命令以及Dockerfile脚本的配置,很快就能上手。