容器技术:让多个独立的用户空间运行在同一台宿主机上。
容器只能运行于底层宿主机相同或相似的操作系统。
例如:
可以在Ubuntu中运行RedHat Enterprise Linux,却无法运行Microsoft Windows
容器常用于多租户服务器部署、轻量级沙盒和安全要求不高的隔离环境中。
Docker:能开发的应用程序自动部署到容器的开源引擎。
作用:
组件:
Docker镜像
镜像是基于联合(Union)文件系统的一种层式架构,由一系列指令构成
如:添加一个文件、执行一个命令或打开一个端口
Registry
用于保存用户构建的镜像。
Docker容器
镜像是Docker生命周期的构建和打包阶段,容器是启动或执行阶段
总而言之,可以把Docker理解为一个隔离的环境。
$ sudo docker run -t -i ubuntu /bin/bash
ubuntu
指定容器的镜像为ubuntu镜像/bin/bash
是示例中要执行的命令,能启动一个Bash shell结果:
最末行的root@6013408ebadd:/#
就是该容器的shell
注:
//检查容器主机名
$ hostname
//检查容器/etc/hosts文件
$ cat /etc/hosts
//检查容器进程
$ ps -aux
//安装软件包,此处安装了Vim软件
$ apt-get update && apt-get install vim
//退出
$ exit
//列出所有Docker容器(该命令在ubuntu宿主机的terminal中给出
$ sudo docker ps -a
//用--name标志创立一个指定名称的容器
$ sudo docker run --name my_first_docker -i -t ubuntu /bin/bash
//重新启动已经停止的容器
$ sudo docker start 容器名/容器Id
//重新附着到容器上
$ sudo docker attach 容器名/容器Id
上面通过-t -i 两个命令行参数实现了交互式运行的容器(interactive container)
还可以使用 -d 参数来创建一个守护式容器(daemonized container)
有以下特点:
无交互式会话
适合运行应用程序和服务
可以长期运行
$ sudo docker run --name daemon_dave -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done"
自-c后面的部分使用了一个while循环,在容器运行期间会一直打印hello world
//获取容器日志
$ sudo docker logs 容器名/id
//跟踪守护式容器的日志没,利用参数-f,使用crtl+c退出
$ sudo docker logs -f 容器名/id
//使用-t参数找到每条日志的时间
$ sudo docker logs -ft 容器名/id
//查看容器内进程
$ sudo docker top 容器名/id
//查看docker统计信息
$ sudo docker stats 一系列守护式容器名,以空格键分隔
//停止守护式容器
$ sudo docker stop 容器名/容器id
//显示最后x个容器,无论容器是运行还是停止
$ sudo docker ps -n x
docker日志驱动:
docker日志驱动
容器内运行的进程分为后台任务和交互式任务
使用docker exec在容器创建新的进程
示例:
$ sudo docker exec -d daemon_dave touch /etc/new_config_file
可以使用参数 -t -i创建交互式进程
//在指定容器中创建一个新的bash会话
$ sudo docker exec -t -i 容器名 /bin/bash
自动重启容器:若因某种错误导致容器停止,则应重启容器
–restart 标志会在检查容器退出代码,并依次决定是否重启容器
$ sudo docker run --restart=可选标志 --name 容器名 -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done"
可选标志:
删除容器:
$ sudo docker rm 容器名/id
//删除运行中的容器
$ sudo docker rm -f 容器名/id
//删除所有容器,首先停止容器运行,然后删除
$ sudo docker stop $(sudo docker ps -a -q)
$ sudo docker rm $(sudo docker ps -a -q)
暂时搁置
镜像来源于仓库,仓库存在于Registry中
默认的Registry是Docker Hub
仓库:包括镜像/层以及关于镜像的元数据
每个仓库中可存储多个镜像
使用标签区分一个仓库下的不同镜像
//列出镜像
$ sudo docker images
//从仓库中拉取Ubuntu镜像
$ suodo docker pull ubuntu:标签
//查看指定镜像
$ sudo docker images 镜像名
docker
Docker Hub中有两种类型的仓库:
用户仓库(user repository):由用户创建
命名:用户名/仓库名
顶层仓库(top-level repository):由Docker内部管理
命名:仓库名
用Dockerfile的定义文件和docker build命令来构建镜像
首先,创建目录用来保存Dockerfile
//创建目录
$ mkdir 目录名
//移到该目录
$ cd 目录名
//建立新文件
touch Dockerfile
//或
vim Dockerfile
然后,在新文件中编译
# Version 0.0.1
FROM 仓库名(:标签)
MAINTAINER hwc "[email protected]"
RUN ..
EXPOSE
每条指令(如FROM)必须为大写字母,后面跟随一个参数
最后,运行Dockerfile
$ cd 目录名
$ sudo docker build -t="仓库名/镜像名" .
//设置标签
$ sudo docker build -t="仓库名/镜像名:v1" .
//查看镜像如何构建
$ sudo docker history 镜像名/id
若没有指定任何标签,则会自动添加latest标签
示例:
$ sudo docker run -d -p 80 --name 容器名称 仓库名称/镜像名称 \nginx -g "daemon off;"
nginx -g "daemon off;"
,这将以前台的方式启动Nginx,作为Web服务器Docker可通过两种方法来在宿主机上分配端口:
查看端口映射情况:
$ sudo docker ps -l
$ sudo docker port 容器id/名称 容器端口号
如:
使用-P参数来对外公开在Dockerfile中通过EXPOSE指令指定的所有端口:
$ sudo docker run -d -P --name 容器名 仓库名/镜像名 \nginx -g "daemon off;"
用于指定容器启动时要运行的命令
与之对比,RUN指定镜像被构建时要运行的命令
两者等效:
$ sudo docker run -i -t demo/test web /bin/true
CMD ["/bin/true"]
//可为CMD指定参数:
CMD ["/bin/bash","-l"]
注意:要运行的命令存放在一个数组结构中
docker run命令可覆盖CMD命令:
当用CMD指定容器启动时要运行的命令后:
#没有指定要运行的命令,将使用CMD指令中的命令
$ sudo docker run -i -t demo/test
#覆盖本地命令
$ sudo docker run -i -t demo/test 新命令
与CMD的区别:
可以在docker run 中覆盖CMD的命令,而ENTRYPOINT的命令不容易在启动容器时被覆盖
docker run中的任何参数都会作为参数传递给ENTRYPOINT中指定的命令
看如下例子:
首先,设置ENTRYPOINT
ENTRYPOINT ["/usr/sbin/nginx"]
然后构建镜像
$ sudo docker build -t="demo/test" .
最后启动容器
$ sudo docker run -i -t demo/test -g "daemon off;"
这里指定了-g "daemon off;"
的参数
这样,会构成命令:
/usr/sbin/nginx -g "daemon off;"
组合使用ENTRYPOINT和CMD:
如:
ENTRYPOINT ["/usr/sbin/nginx"]
CMD ["-h"]
此时,当在docker run命令中指定其它参数(如-g "daemon off;"
)时,会覆盖CMD中参数,否则,会运行默认的命令
用于从镜像创建一个新容器时,在容器内部设置一个工作目录
如:
WORKDIR /opt/webapp/db
RUN bundle install
WORKDIR /opt/webapp
ENTRYPOINT ["rackup"]
首先将工资目录切换为/opt/webapp/db后,运行bundle,然后又切换为/opt/webapp,设置ENTRYPOINT
可使用 -w 标志在运行时覆盖工作目录:
$ sudo docker run ti -w 指定目录 ubuntu pwd
用于在镜像构建过程中设置环境变量
示例:
#Ddockerfile:
ENV RVM_PATH /home/rvm/
#为RUN指令设置前缀:
RUN gem install unicorn
#上述两语句等价于:
RUN RVM_PATH=/home/rvm/ gem install unicorn
#也可用于设置多个环境变量
ENV RVM_PATH=/home/rvm/ RVM_ARCHFLAGS="-arch i386"
#可在其他Dokcerfile指令中使用环境变量:
#WORKDIR指令的值会被设为/opt/app
ENV TARGET_DIR /opt/app
WORKDIR $TARGET_DIR
用ENV设置的环境变量会保存到任何该镜像创建的容器中
也可以使用docker run命令行-标志来传递环境变量,这些变量只会在运行时有效
例子:
$ sudo docker run -ti -e "WEB_PORT=8000" ubuntu env
指定该镜像会以是什么样的用户去运行
示例:
USER 用户名
USER UID
USER 用户名:组名
USER 用户名:GID
USER UID:组名
USER UID:GID
向基于镜像创建的容器添加卷
示例:
#为任何基于此镜像创建的容器创建一个挂载点:/opt/project
VOLUME ["/opt/project"]
#指定多个卷
VOLUME ["/opt/project","/data"]
用于将构建环境下的文件和目录复制到镜像中
示例
# 在安装一个应用程序时,需提供源文件位置和目的文件位置两个参数
# 这里将software.lic文件复制到后面的文件位置中
ADD software.lic /opt/application/software.lic
#也可以使用URL作为文件源
ADD https://www.jetbrains.com/go/download/download-thanks.html?platform=linux
ADD处理本地归档文件(tar archive)(包括gzip,bzip2,xz)时,能将文件解开(unpack)
#将归档文件解压到目的目录
ADD latest.tar.gz /var/www/wordpress/
若目的文件位置不存在,那么会创建该路径。
COPY类似ADD
COPY只复制文件,而不会提取(extraction)和解压(decompression)
其语法与ADD类似
用于为Dokcer镜像添加元数据
形式:键对值
LABEL version="1.0"
LABEL location="WEI HAI" type="Domitpry" role="Web Server"
可以通过多个LABEL命令来添加,但还是建议通过一条LABEL命令来添加所有需要的元数据,因为不同的元数据指令会创建过多的镜像层
查看容器标签:
$ sudo docker inspect demo/test
指定一个变量,在docker build时使用
使用变量:在docker build时传递–build-arg
#添加ARG指令
ARG build
#这里为参数设置了一个默认值
ARG webapp_user=user
#使用ARG指令
#build变量设置成了1234,webapp_user则会使用默认值
$ docker build --build-arg build=1234 -t demo/test
一些预定义ARG变量:
HTTP_PROXY
http_proxy
HTTPS_PROXY
https_proxy
FTP_PROXY
ftp_proxy
NO_PROXY
no_proxy
在Dockerfile中构建一个触发器
当一个镜像被其他镜像作为基础镜像时,该镜像的触发器会执行
其他指令都是为了帮自己订制镜像,而ONBUILD是为了帮他人订制自己
格式:ONBUILD <其他指令>
可用docker inspect命令查看镜像中的ONBUILD命令
$ sudo docker inspect 容器id,容器名
推送镜像:
$ sudo docker push 用户仓库名
$ sudo docker rmi 镜像名1, 镜像名2
#删除所有镜像
$ sudo docker rmi $(sudo docker images -a -q)