1 1.Docker概念简介 2 1.1 Docker的应用场景 3 1.2 Docker的优势 4 1.3 Docker架构 5 1.4 Dorcker核心概念 6 1.4.1 Dockerfile、Docker镜像和Docker容器的关系 7 1.4.2 Dockerfile与Docker镜像 8 1.4.3 Docker镜像与Docker容器的关系 9 1.5 Docker特性 10 1.6 传统虚拟技术的区别 11 1.7 docker 的四种网络模式 12 2. Docker的安装 13 3. Docker命令 14 3.1 容器相关操作 15 3.2 获取容器相关信息 16 3.3 导出容器 17 3.4 镜像操作 18 3.5 镜像仓库(registry)操作 19 3.6 docker其他命令使用示例 20 3.7 docker run详解 21 3.8 docker build 22 4.Docker镜像库操作 23 5. Dockerfile 24 6.Docker镜像的存储位置 25 7.一键部署tomcat目录
1.Docker概念简介
Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源。
Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。
容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。
Docker 和传统虚拟化方式的不同之处,可见容器是在操作系统层面上实现虚拟化,直接复用本地主机的操作系统,而传统方式则是在硬件层面实现。
1.1 Docker的应用场景
a) Web 应用的自动化打包和发布。
b) 自动化测试和持续集成、发布。
c) 在服务型环境中部署和调整数据库或其他的后台应用。
d) 从头编译或者扩展现有的OpenShift或Cloud Foundry平台来搭建自己的PaaS环境。
1.2 Docker的优势
- 更快速的交付和部署
Docker在整个开发周期都可以完美的辅助你实现快速交付。Docker允许开发者在装有应用和服务本地容器做开发。可以直接集成到可持续开发流程中。
例如:开发者可以使用一个标准的镜像来构建一套开发容器,开发完成之后,运维人员可以直接使用这个容器来部署代码。 Docker 可以快速创建容器,快速迭代应用程序,并让整个过程全程可见,使团队中的其他成员更容易理解应用程序是如何创建和工作的。 Docker 容器很轻很快!容器的启动时间是秒级的,大量地节约开发、测试、部署的时间。
- 高效的部署和扩容
Docker 容器几乎可以在任意的平台上运行,包括物理机、虚拟机、公有云、私有云、个人电脑、服务器等。 这种兼容性可以让用户把一个应用程序从一个平台直接迁移到另外一个。
Docker的兼容性和轻量特性可以很轻松的实现负载的动态管理。你可以快速扩容或方便的下线的你的应用和服务,这种速度趋近实时。
- 更高的资源利用率
Docker 对系统资源的利用率很高,一台主机上可以同时运行数千个 Docker 容器。容器除了运行其中应用外,基本不消耗额外的系统资源,使得应用的性能很高,同时系统的开销尽量小。传统虚拟机方式运行 10 个不同的应用就要起 10 个虚拟机,而Docker 只需要启动 10 个隔离的应用即可。
- 更简单的管理
使用 Docker,只需要小小的修改,就可以替代以往大量的更新工作。所有的修改都以增量的方式被分发和更新,从而实现自动化并且高效的管理。
1.3 Docker架构
Docker使用C/S架构,Client 通过接口与Server进程通信实现容器的构建,运行和发布。client和server可以运行在同一台集群,也可以通过跨主机实现远程通信。
1.4 Dorcker核心概念
镜像(image)
Docker 镜像(Image)就是一个只读的模板。镜像可以用来创建 Docker 容器,一个镜像可以创建很多容器。Docker 提供了一个很简单的机制来创建镜像或者更新现有的镜像,用户甚至可以直接从其他人那里下载一个已经做好的镜像来直接使用。
容器(container)
Docker 利用容器(Container)独立运行的一个或一组应用。容器是从镜像创建的运行实例。它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。
容器的定义和镜像几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的。
仓库(repository)
仓库(Repository)是集中存放镜像文件的场所。有时候会把仓库和仓库注册服务器(Registry)混为一谈,并不严格区分。实际上,仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。
仓库分为公开仓库(Public)和私有仓库(Private)两种形式。最大的公开仓库是 Docker Hub,存放了数量庞大的镜像供用户下载。国内的公开仓库包括 时速云 、网易云 等,可以提供大陆用户更稳定快速的访问。当然,用户也可以在本地网络内创建一个私有仓库。
当用户创建了自己的镜像之后就可以使用 push 命令将它上传到公有或者私有仓库,这样下次在另外一台机器上使用这个镜像时候,只需要从仓库上 pull 下来就可以了。
Docker 仓库的概念跟 Git 类似,注册服务器可以理解为 GitHub 这样的托管服务。
1.4.1 Dockerfile、Docker镜像和Docker容器的关系
Dockerfile 是软件的原材料,Docker 镜像是软件的交付品,而 Docker 容器则可以认为是软件的运行态。从应用软件的角度来看,Dockerfile、Docker 镜像与 Docker 容器分别代表软件的三个不同阶段,Dockerfile 面向开发,Docker 镜像成为交付标准,Docker 容器则涉及部署与运维,三者缺一不可,合力充当 Docker 体系的基石。
简单来讲,Dockerfile构建出Docker镜像,通过Docker镜像运行Docker容器。
我们可以从Docker容器的角度,来反推三者的关系。首先可以来看下图:
我们假设这个容器的镜像通过以下Dockerfile构建而得:
简单的dockerfile1 FROM ubuntu:14.04 2 ADD run.sh / 3 VOLUME /data 4 CMD ["./run.sh"]
1.4.2 Dockerfile与Docker镜像
首先,我们结合上图来看看Dockerfile与Docker镜像之间的关系。
FROM ubuntu:14.04:设置基础镜像,此时会使用基础镜像 ubuntu:14.04 的所有镜像层,为简单起见,图中将其作为一个整体展示。
ADD run.sh /:将 Dockerfile 所在目录的文件 run.sh 加至镜像的根目录,此时新一层的镜像只有一项内容,即根目录下的 run.sh。
VOLUME /data:设定镜像的 VOLUME,此 VOLUME 在容器内部的路径为 /data。需要注意的是,此时并未在新一层的镜像中添加任何文件,即构建出的磁层镜像中文件为空,但更新了镜像的 json 文件,以便通过此镜像启动容器时获取这方面的信息。
CMD ["./run.sh"]:设置镜像的默认执行入口,此命令同样不会在新建镜像中添加任何文件,仅仅在上一层镜像 json 文件的基础上更新新建镜像的 json 文件。
因此,通过以上分析,以上的Dockerfile可以构建出一个新的镜像,包含4个镜像层,每一条命令会和一个镜像层对应,镜像之间会存在父子关系。图中很清楚的表明了这些关系。
1.4.3 Docker镜像与Docker容器的关系
Docker镜像是Docker容器运行的基础,没有Docker镜像,就不可能有Docker容器,这也是Docker的设计原则之一。
可以理解的是:Docker镜像毕竟是镜像,属于静态的内容;而Docker容器就不一样了,容器属于动态的内容。动态的内容,大家很容易联想到进程,内存,CPU等之类的东西。的确,Docker容器作为动态的内容,都会包含这些。
为了便于理解,大家可以把Docker容器,理解为一个或多个运行进程,而这些运行进程将占有相应的内存,相应的CPU计算资源,相应的虚拟网络设备以及相应的文件系统资源。而Docker容器所占用的文件系统资源,则通过Docker镜像的镜像层文件来提供。
那么作为静态的镜像,如何才有能力转化为一个动态的Docker容器呢?此时,我们可以想象:第一,转化的依据是什么;第二,由谁来执行这个转化操作。
其实,转化的依据是每个镜像的json文件,Docker可以通过解析Docker镜像的json的文件,获知应该在这个镜像之上运行什么样的进程,应该为进程配置怎么样的环境变量,此时也就实现了静态向动态的转变。
谁来执行这个转化工作?答案是Docker守护进程。也许大家早就理解这样一句 话:Docker容器实质上就是一个或者多个进程,而容器的父进程就是Docker守护进程。这样的,转化工作的执行就不难理解了:Docker守护进程 手握Docker镜像的json文件,为容器配置相应的环境,并真正运行Docker镜像所指定的进程,完成Docker容器的真正创建。
Docker容器运行起来之后,Docker镜像json文件就失去作用了。此时Docker镜像的绝大部分作用就是:为Docker容器提供一个文件系统的视角,供容器内部的进程访问文件资源。
再次回到上图,我们再来看看容器和镜像之间的一些特殊关系。首先,之前已经提及Docker镜像是分层管理的,管理Docker容器的时候,Docker镜像仍然是分层管理的。由于此时动态的容器中已经存在进程,进程就会对文件系统视角内的文件进行读写操作,因此,就会涉及一个问题:容器是否会篡改Docker镜像的内容?
答案自然是不会的。统一来讲,正如上图,所有的Docker镜像层对于容器来说,都是只读的,容器对于文件的写操作绝对不会作用在镜像中。
既然如此,实现的原理就很重要,究其根本:Docker守护进程会在Docker镜像的 最上层之上,再添加一个可读写层,容器所有的写操作都会作用到这一层中。而如果Docker容器需要写底层Docker镜像中的文件,那么此时就会涉及一 个叫Copy-on-Write的机制,即aufs等联合文件系统保证:首先将此文件从Docker镜像层中拷贝至最上层的可读写层,然后容器进程再对读 写层中的副本进行写操纵。对于容器进程来讲,它只能看到最上层的文件。
那最后我们再来说说:Docker容器的文件系统视角中,到底是不是存在一些内容,不是存储于Docker镜像中的?
这次的答案依旧是肯定的。
再次重申一点,Docker镜像中存储的都是一些静态文件。这些文件原则上应该和容器具体信息以及主机信息完全解藕。那么Docker容器中不存在Docker镜像中的内容主要有以下几点:
1./proc以及/sys等虚拟文件系统的内容
2.容器的hosts文件,hostname文件以及resolv.conf文件,这些事具体环境的信息,原则上的确不应该被打入镜像。
3.容器的Volume路径,这部分的视角来源于从宿主机上挂载到容器内部的路径
4.部分的设备文件
1.5 Docker特性
文件系统隔离:每个进程容器运行在完全独立的根文件系统里。
资源隔离:可以使用cgroup为每个进程容器分配不同的系统资源,例如CPU和内存。
网络隔离:每个进程容器运行在自己的网络命名空间里,拥有自己的虚拟接口和IP地址。
写时复制:采用写时复制方式创建根文件系统,这让部署变得极其快捷,并且节省内存和硬盘空间。
日志记录:Docker将会收集和记录每个进程容器的标准流(stdout/stderr/stdin),用于实时检索或批量检索。
变更管理:容器文件系统的变更可以提交到新的映像中,并可重复使用以创建更多的容器。无需使用模板或手动配置。
交互式Shell:Docker可以分配一个虚拟终端并关联到任何容器的标准输入上,例如运行一个一次性交互shell。
1.6 传统虚拟技术的区别
Docker类似虚拟机的概念,但是与虚拟化技术的不同点在于下面几点:
1. 虚拟化技术依赖物理CPU和内存,是硬件级别的;而docker构建在操作系统上,利用操作系统的containerization技术,所以docker甚至可以在虚拟机上运行
2. 虚拟化系统一般都是指操作系统镜像,比较复杂,称为“系统”;而docker开源而且轻量,称为“容器”,单个容器适合部署少量应用,比如部署一个redis、一个memcached。
3. 传统的虚拟化技术使用快照来保存状态;而docker在保存状态上不仅更为轻便和低成本,而且引入了类似源代码管理机制,将容器的快照历史版本一一记录,切换成本很低。
4. 传统的虚拟化技术在构建系统的时候较为复杂,需要大量的人力;而docker可以通过Dockfile来构建整个容器,重启和构建速度很快。更重要的是Dockfile可以手动编写,这样应用程序开发人员可以通过发布Dockfile来指导系统环境和依赖,这样对于持续交付十分有利。
5. Dockerfile可以基于已经构建好的容器镜像,创建新容器。Dockerfile可以通过社区分享和下载,有利于该技术的推广。
Docker会像一个可移植的容器引擎那样工作。它把应用程序及所有程序的依赖环境打包到一个虚拟容器中,这个虚拟容器可以运行在任何一种 Linux服务器上。这大大地提高了程序运行的灵活性和可移植性,无论需不需要许可、是在公共云还是私密云、是不是裸机环境等等。
1.7 docker 的四种网络模式
host模式
container模式
none模式
bridge模式默认模式
docker run -it --rm --net=host centos_with_net bash
使用--net=container:container_id/container_name,多个容器使用共同的网络看到的ip是一样
使用--net=none指定,这种模式下不会配置任何网络。
使用--net=bridge指定,不用指定默认就是这种网络模式。这种模式会为每个容器分配一个独立的Network Namespace。类似于Vmware的nat网络模式。同一个宿主机上的所有容器会在同一个网段下,相互之间是可以通信的。
host模式
如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。
但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。
container模式
Container模式指定新创建的容器和已经存在的一个容器共享一个Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过lo网卡设备通信。
none模式
使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。
bridge模式
bridge模式是Docker默认的网络设置,此模式会为每一个容器分配Network Namespace、设置IP等,并将一个主机上的Docker容器连接到一个虚拟网桥上。
2. Docker的安装
前提条件:
目前,CentOS 仅发行版本中的内核支持 Docker。
Docker 运行在 CentOS 7 上,要求系统为64位、系统内核版本为 3.10 以上。
Docker 运行在 CentOS-6.5 或更高的版本的 CentOS 上,要求系统为64位、系统内核版本为 2.6.32-431 或者更高版本。(uname –r查看内核版本)
1 [root@localhost /]# yum -y install docker-io #yum安装docker 2 3 [root@localhost /]# vi /etc/sysconfig/docker #更改配置文件 4 5 other-args列更改为:other_args="--exec-driver=lxc--selinux-enabled" 6 7 启动docker服务 8 [root@localhost /]# service docker start #启动docker 9 10 Starting cgconfig service: [ OK ] 11 12 Starting docker: [ OK ] 13 14 [root@localhost /]# chkconfig docker on #将docker加入开机启动 15 16 [root@localhost /]# docker version #基本信息查看 17 Client version: 1.0.0 18 Client API version: 1.12 19 Go version (client): go1.2.2 20 Git commit (client): 63fe64c/1.0.0 21 Server version: 1.0.0 22 Server API version: 1.12 23 Go version (server): go1.2.2 24 Git commit (server): 63fe64c/1.0.0 25 26 #docker info:查看系统(docker)层面信息,包括管理的images, containers数等 27 [root@localhost /]# docker info 28 Containers: 16 29 Images: 40 30 Storage Driver: devicemapper 31 Pool Name: docker-253:0-1183580-pool 32 Data file: /var/lib/docker/devicemapper/devicemapper/data 33 Metadata file: /var/lib/docker/devicemapper/devicemapper/metadata 34 Data Space Used: 2180.4 Mb 35 Data Space Total: 102400.0 Mb 36 Metadata Space Used: 3.4 Mb 37 Metadata Space Total: 2048.0 Mb 38 Execution Driver: lxc-0.9.0 39 Kernel Version: 2.6.32-431.el6.x86_64View Code
3. Docker命令
3.1 容器相关操作
docker create # 创建一个容器但是不启动它
示例:
1.使用docker镜像nginx:latest创建一个容器,并将容器命名为myrunoob
docker create --name myrunoob nginx:latest 09b93464c2f75b7b69f83d56a9cfc23ceb50a48a9db7652ee4c27e3e2cb1961f
docker stop # 停止容器运行,发送信号SIGTERM
docker start # 启动一个停止状态的容器
docker restart # 重启一个容器
示例:
1.启动|停止|重启容器myrunoob
docker start|stop|restart myrunoob
docker rm # 删除一个容器
-f :通过SIGKILL信号强制删除一个运行中的容器
-l :移除容器间的网络连接,而非容器本身
-v :-v 删除与容器关联的卷
示例:
1.强制删除容器db01、db02
docker rm -f db01、db02
2.移除容器nginx01对容器db01的连接,连接名db
docker rm -l db
3.删除容器nginx01,并删除容器挂载的数据卷
docker rm -v nginx01
4.删除老的(一周前创建)容器
docker ps -a | grep 'weeks ago' | awk '{print $1}' | xargs docker rm
5.删除已经停止的容器
docker rm `docker ps -a -q`
6.删除所有镜像,小心
docker rmi $(docker images -q)
docker kill # 发送信号给容器,默认SIGKILL
示例:
1.杀掉运行中的容器mynginx
docker kill -s KILL mynginx
2.杀掉所有正在运行的容器
docker kill $(docker ps -q)
docker pause #暂停容器中所有的进程。
docker unpause #恢复容器中所有的进程。
示例:
暂停数据库容器db01提供服务。
docker pause db01
恢复数据库容器db01提供服务。
docker unpause db01
3.2 获取容器相关信息
docker ps # 显示状态为运行(Up)的容器
docker ps -a # 显示所有容器,包括运行中(Up)的和退出的(Exited)
docker inspect #检查镜像或者容器的参数,默认返回 JSON 格式。
示例:
1.docker inspect --format '{{.DockerVersion}}' ubuntu:14.04
上面命令的意思是返回 ubuntu:14.04 镜像的 docker 版本
-f, --format= 指定返回值的模板文件
2.获取Container IP地址(Container状态必须是Up)
docker inspect id | grep IPAddress | cut -d '"' -f 4
3.获取端口映射
docker inspect -f '{{range $p, $conf := .NetworkSettings.Ports}} {{$p}} -> {{(index $conf 0).HostPort}} {{end}}' id
docker logs # 查看容器的日志(stdout/stderr),-f实时查看
示例:
查看容器mynginx从2016年7月1日后的最新10条日志。
1.docker logs --since="2016-07-01" --tail=10 mynginx
docker events # 得到docker服务器的实时的事件
示例:
1.从服务器拉取个人动态,可选择时间区间。
docker events --since="20150720" --until="20150808"
上面命令的意思是拉取个人从 2015/07/20 到 2015/08/08 的个人动态。
参数:
--since= 开始时间
--until= 结束时间
docker port # 显示容器的端口映射
docker top # 显示容器的进程信息
docker diff # 显示容器文件系统的前后变化
查看容器mynginx的端口映射情况。
docker port mymysql
3306/tcp -> 0.0.0.0:3306
3.3 导出容器
docker cp # 从容器里向外拷贝文件或目录
示例:
1.复制容器里的文件到宿主机上
docker cp 90af375815d4:/var/jenkins_home/workspace /target/HelloWorld.war ~
docker export # 将容器整个文件系统导出为一个tar包,不带layers、tag等信息。docker import 的逆操作。导出后导入(exported-imported))的容器会丢失所有的提交历史,无法回滚。
示例:
1.docker export -o ubuntu14.04.tar 94c6b3c3f04a
上面命令的意思是将 ID 为 94c6b3c3f04a 容器保存为 ubuntu14.04.tar 文件。
参数:
-o, --output= Write to a file, instead of STDOUT
docker exec # 在容器里执行一个命令,可以执行bash进入交互式
示例:
1.docker exec -it 90af375815d4 /bin/bash
2.执行容器内的脚本runoob.sh
docker exec -it mynginx /bin/sh /root/runoob.sh
3.获取环境变量
docker exec container_id env
3.4 镜像操作
docker images # 显示本地所有的镜像列表
docker import # 从一个tar包创建一个镜像,往往和export结合使用
示例:
1.cat ./ubuntu14.04.tar | sudo docker import - ubuntu:14.04
上面命令的意思是使用 ./ubuntu14.04.tar 文件创建 ubuntu:14.04 的镜像,默认会从远端拉取文件。
docker build # 使用Dockerfile创建镜像(推荐)
docker commit # 从容器创建镜像
docker rmi # 删除一个镜像
docker load # 从一个tar包创建一个镜像,和save配合使用
示例:
1.docker load -i ubuntu14.04.tar
上面命令的意思是将 ubuntu14.04.tar 文件载入镜像中。
参数:
-i, --input= Read from a tar archive file, instead of STDIN 加载的tar文件
docker save # 将一个镜像保存为一个tar包,带layers和tag信息,docker load 的逆操作。保存后再加载(saved-loaded)的镜像不会丢失提交历史和层,可以回滚。
示例:
1.docker save -o ubuntu14.04.tar ubuntu:14.04
上面命令的意思是将镜像 ubuntu:14.04 保存为 ubuntu14.04.tar 文件。
参数:
-o, --output= Write to an file, instead of STDOUT 输出到的文件
docker history # 显示生成一个镜像的历史命令
示例:
1.docker history -H harrysun/lnmp:0.1
上面命令的意思是查看 harrysun/lnmp:0.1 镜像的历史。
-H, --human=true Print sizes and dates in human readable format 以可读的格式打印镜像大小和日期
--no-trunc=false Don't truncate output 显示完整的提交记录
-q, --quiet=false Only show numeric IDs 仅列出提交记录ID
docker tag # 为镜像起一个别名
示例:
1.将镜像ubuntu:15.10标记为 runoob/ubuntu:v3 镜像。
docker tag ubuntu:15.10 runoob/ubuntu:v3
3.5 镜像仓库(registry)操作
docker login # 登录到一个registry
docker logout #运行后从指定服务器登出,默认为官方服务器。
docker search # 从registry仓库搜索镜像
docker pull # 从仓库下载镜像到本地
docker push # 将一个镜像push到registry仓库中
3.6 docker其他命令使用示例
3.7 docker run详解
docker run :创建一个新的容器并运行一个命令
-a stdin 指定标准输入输出内容类型,可选 STDIN/STDOUT/STDERR 三项;
-C 共享CPU
--cidfile=“” 将容器的ID标识写入文件
-d 后台运行容器,并返回容器ID;
--dns 8.8.8.8 指定容器使用的DNS服务器,默认和宿主一致;
-e, --env=[] 指定环境变量,容器中可以使用该环境变量
--env-file=[] 指定环境变量文件,文件格式为每行一个环境变量
--expose=[] 指定容器暴露的端口,即修改镜像的暴露端口
-h, --hostname="" 指定容器的主机名
-I 以交互模式运行容器,通常与 -t 同时使用;
-t 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
--link=[] 添加链接到另一个容器;
--name="" 指定容器名字,后续可以通过名字进行容器管理,links特性需要使用名字;
-n 允许镜像使用网络
--net="bridge" 容器的网络连接类型,支持 bridge/host/none/container: 四种类型;
--cpuset="0-2" or --cpuset="0,1,2" 绑定容器到指定CPU运行;
-m 设置容器使用内存最大值;
-P Docker 会随机映射一个端口到内部容器开放的网络端口。
-p 可以指定要映射的端口,在一个指定端口上只可以绑定一个容器。支持的格式有 ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort。
--rm=false 容器停止后自动删除容器(不支持以docker run -d启动的容器)
--restart="" 指定容器停止后的重启策略,待详述
-u, --user="" 指定容器的用户
-v, --volume=[] 给容器挂载存储卷,挂载到容器的某个目录
--volumes-from=[] 给容器挂载其他容器上的卷,挂载到容器的某个目录
-w, --workdir="" 指定容器的工作目录
使用docker镜像nginx:latest以后台模式启动一个容器,并将容器命名为mynginx。
docker run --name mynginx -d nginx:latest
使用镜像nginx:latest以后台模式启动一个容器,并将容器的80端口映射到主机随机端口。
docker run -P -d nginx:latest
使用镜像nginx:latest以后台模式启动一个容器,将容器的80端口映射到主机的80端口,主机的目录/data映射到容器的/data。
docker run -p 80:80 -v /data:/data -d nginx:latest
使用镜像nginx:latest以交互模式启动一个容器,在容器内执行/bin/bash命令。
docker run -it nginx:latest /bin/bash
root@b8573233d675:/#
可以通过-link name:alias命令连接指定容器,Docker 在两个互联的容器之间创建了一个安全隧道,而且不用映射它们的端口到宿主主机上,从而避免了暴露数据库端口到外部网络上。
使用 –name 选项可以为容器自定义命名,容器的名字必须是唯一的。然后创建一个web容器,连接到数据库容器。
docker run -d -P --name web --link db:db training/webapp python app.py
-p和-P用法
docker run -d -P training/webapp python app.py
docker run -d -p 5000:5000 training/webapp python app.py
3.8 docker build
OPTIONS说明:
--add-host 添加自定义的主机到IP映射(主机:ip)
--build-arg=[] 设置镜像创建时的变量;
--cpu-shares 设置 cpu 使用权重;
--cpu-period 限制 CPU CFS周期;
--cpu-quota 限制 CPU CFS配额;
--cpuset-cpus 指定使用的CPU id;
--cpuset-mems 指定使用的内存 id;
--disable-content-trust 忽略校验,默认开启;
-f ,--file 指定要使用的Dockerfile路径;
--force-rm 设置镜像过程中删除中间容器;
--isolation 使用容器隔离技术;
--label=[] 设置镜像使用的元数据;
-m,--memory 设置内存最大值;
--memory-swap 设置Swap最大值为内存+swap,"-1"表示不限swap;
--no-cache 创建镜像的过程不使用缓存;
--pull 尝试去更新镜像的新版本;
-q 安静模式,成功后只输出镜像ID;
--rm 设置镜像成功后删除中间容器;
--shm-size 设置/dev/shm的大小,默认值是64M;
--ulimit Ulimit配置。
--tag, -t, 镜像的名字及tag,通常name:tag或者name格式;可以在一次构建中为一个镜像设置多个tag
实例:
1.使用当前目录的Dockerfile创建镜像。
docker build -t runoob/ubuntu:v1 .
2.使用URL github/creack/docker-firefox 的 Dockerfile 创建镜像。
docker build github/creack/docker-firefox
3. 搬运工人将标准输入输入的指定文件打包进去
docker build -<Dockerfile
4. 支持压缩格式bzip2,gzip和xz。
docker build -< context.tar.gz
4.Docker镜像库操作
1.从docker hub官方镜像仓库拉取镜像
# docker pull busybox:latest
atest: Pulling from busybox
cf2616975b4a: Pull complete
6ce2e90b0bc7: Pull complete
8c2e06607696: Already exists
busybox:latest: The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security.
Digest: sha256:38a203e1986cf79639cfb9b2e1d6e773de84002feea2d4eb006b52004ee8502d
Status: Downloaded newer image for busybox:latest
2.从本地上传镜像到镜像仓库
docker push 192.168.1.2/csphere/nginx:1.7
3.查找镜像仓库的某个镜像
# docker search centos/nginx
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
johnnyzheng/centos-nginx-php-wordpress 1 [OK]
sergeyzh/centos6-nginx 1 [OK]
hzhang/centos-nginx 1 [OK]
4.查看本地镜像列表
# docker images
TAG IMAGE ID CREATED VIRTUAL SIZE
docker.io/csphere/csphere 0.10.3 604c03bf0c9e 3 days ago 62.72 MB
docker.io/csphere/csphere latest 604c03bf0c9e 3 days ago 62.72 MB
csphere/csphere 0.10.3 604c03bf0c9e 3 days ago 62.72 MB
registry 2.0 2971b6ce766c 7 days ago 548.1 MB
busybox latest 8c2e06607696 3 weeks ago 2.43 MB
5.删除镜像
docker rmi busybox:latest #没有容器使用此镜像创建,如果有容器在使用此镜像会报错:Error response from daemon: Conflict, cannot delete 8c2e06607696 because the running container 831c93de9b9f is using it, stop it and use -f to force
FATA[0000] Error: failed to remove one or more images
docker rmi -f busybox:latest #容器使用此镜像创建,此容器状态为Exited
6.查看构建镜像所用过的命令
# docker history busybox:latest
IMAGE CREATED CREATED BY SIZE
8c2e06607696 3 weeks ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0 B
6ce2e90b0bc7 3 weeks ago /bin/sh -c #(nop) ADD file:8cf51 2.43 MB
cf2616975b4a 3 weeks ago /bin/sh -c #(nop) MAINTAINER 0 B
5. Dockerfile
指令忽略大小写,分为构建指令和设置指令。
构建指令用于构建images,操作不会在image的容器上执行。
设置指令用来设置image的属性,将在image里执行
Dockerfile是docker构建镜像的基础,也是docker区别于其他容器的重要特征,正是有了Dockerfile,docker的自动化和可移植性才成为可能。
不论是开发还是运维,学会编写Dockerfile几乎是必备的,这有助于你理解整个容器的运行。
FROM 从一个基础镜像构建新的镜像(可以远程,也可以本地)
MAINTAINER 维护者信息
ENV 设置环境变量
RUN 非交互式运行shell命令
ADD 将外部文件拷贝到镜像里,src可以为url
COPY(建议使用) 拷贝到container里,文件权限默认为0755,如果是一个目录,将目录下的文件拷贝,不包括目录,不适用/结束,会视为文件
WORKDIR /path/to/workdir 设置工作目录,相当于cd
USER 设置用户ID
VOULUME <#dir> 设置volume
EXPOSE 暴露哪些端口
ENTRYPOINT [‘executable’,‘param1’]执行命令,同下
CMD [“param1”,”param2”] 设置container启动时执行的操作,可以自定义脚本,只能存在一次,多个只会执行最后一条
示例:
FROM ubuntu
MAINTAINER William <wlj@nicescale>
ENV TEST 1
RUN apt-get -y update
RUN apt-get -y install nginx
ADD http://nicescale/ /data/nicescale.tgz
COPY jdk1.6 /usr/local/java
WORKDIR /var/www
USER nginx
VOLUME [‘/data’]
EXPOSE 80 443
ENTRYPOINT ["/usr/sbin/nginx"]
CMD ["start"]
注意事项:
1.docker创建、启动container时执行的命令,如果设置了ENTRYPOINT,则CMD将作为参数
2.Dockerfile 使用#来注释
编写完成 Dockerfile 后可以使用 docker build 来生成镜像。
$ docker build -t hainiu/httpd:1.0 .
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM centos:centos6
---> 6a77ab6655b9
Step 2 : MAINTAINER sandywei <sandy@hainiu.tech>
---> Running in 1b26493518a7
---> 8877ee5f7432
Removing intermediate container 1b26493518a7
Step 3 : RUN yum install -y httpd
---> Running in fe5b6f1ef888
.....
Step 5 : CMD sh -c service httpd start
---> Running in b2b94c1601c2
---> 5f9aa91b0c9e
Removing intermediate container b2b94c1601c2
Successfully built 5f9aa91b0c9e 执行结果
其中 -t 标记来添加 tag,指定新的镜像的用户信息。 “.” 是 Dockerfile 所在的路径(当前目录),也可以替换为一个具体的 Dockerfile 的路径。注意一个镜像不能超过 127 层。
用docker images 查看镜像列表
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hainiu/httpd 1.0 5f9aa91b0c9e 3 minutes ago 292.4 MB
centos centos6 6a77ab6655b9 8 weeks ago 194.6 MB
ubuntu latest 2fa927b5cdd3 9 weeks ago 122 MB
细心的朋友可以看到最后一层的ID(5f9aa91b0c9e)和 image id 是一样的
6.Docker镜像的存储位置
很多朋友在初学 docker 的时候非常迷茫,不清楚 docker 是怎样的一种存储方式,并且也不清楚 docker 到底存储在什么地方。其实 docker 的镜像与容器都存储在 /var/lib/docker 下面,那么基于不同的系统又有不同的存储方式,在 ubuntu 下面存储方式为 AUFS;在 Centos 下面存储方式又是 device mapper,下面我们先来看一下 /var/lib/docker 目录,分别有三个阶段,看看在不同阶段都新增了那些东西及镜像与容器存储结构的变化:
Docker实际上把所有东西都放到/var/lib/docker路径下了。
[root@docker-100 docker]# tree ./
./
├── containers
├── devicemapper
│ ├── devicemapper
│ │ ├── data
│ │ └── metadata
│ └── metadata
│ ├── base
│ ├── deviceset-metadata
│ └── transaction-metadata
├── graph
├── linkgraph.db
├── repositories-devicemapper
├── tmp
├── trust
└── volumes
1、/var/lib/docker/devicemapper/devicemapper/data #用来存储相关的存储池数据
2、/var/lib/docker/devicemapper/devicemapper/metadata #用来存储相关的元数据。
3、/var/lib/docker/devicemapper/metadata/ #用来存储 device_id、大小、以及传输_id、初始化信息
4、/var/lib/docker/devicemapper/mnt #用来存储挂载信息
5、/var/lib/docker/container/ #用来存储容器信息
6、/var/lib/docker/graph/ #用来存储镜像中间件及本身详细信息和大小,以及依赖信息
7、/var/lib/docker/repositores-devicemapper #用来存储镜像基本信息
8、/var/lib/docker/tmp #docker临时目录
9、/var/lib/docker/trust #docker信任目录
10、/var/lib/docker/volumes #docker卷目录
7.一键部署tomcat
1 shell脚本: 2 3 #!/bin/sh 4 5 # deploy options 6 7 8 9 project=basic-web 10 11 12 13 # 要部署的目录 14 15 deploy_dir=/app/deploy/$project 16 17 18 19 20 21 # svn options 22 23 project_svn_uri=svn://192.168.1.108/test/basic-web 24 25 svn_base_dir=/usr/local/svn-projects/ 26 27 svn_user=massive 28 29 svn_password=massive 30 31 32 33 34 35 36 37 # docker options 38 39 # 接收 -p 参数,若没传此参数则取默认端口8080 40 41 port=8080 42 43 while getopts ":p:" opt; do 44 45 case $opt in 46 47 p) 48 49 port=$OPTARG #get the value 50 51 ;; 52 53 ?) 54 55 echo "How to use: $0 [-p port]" >&2 56 57 exit 1 58 59 ;; 60 61 :) 62 63 echo "Option -$OPTARG requires an argument." >&2 64 65 exit 1 66 67 ;; 68 69 esac 70 71 done 72 73 74 75 76 77 # 取svn地址最后一个`/`字符后面的名称作为checkout出来的目录 78 79 svn_full_dir=$svn_base_dir${project_svn_uri##*/} 80 81 82 83 84 85 echo '----------------------------------------------' 86 87 echo "checkout project : ${project_svn_uri}" 88 89 echo "checkout diretory : ${svn_full_dir}" 90 91 echo "deploy project : ${deploy_dir}" 92 93 echo "deploy port : ${port}" 94 95 echo '----------------------------------------------' 96 97 98 99 100 101 # ------------------------------------ 102 103 # checkout or update from svn 104 105 # ------------------------------------ 106 107 cd $svn_full_dir 108 109 110 111 echo "try to get svn info..." 112 113 svn info 114 115 # 如果svn info命令执行成功,证明项目已checkout,否则就未checkout 116 117 # 若未checkout则checkout项目,否则update项目至最新版本 118 119 if [ $? -eq 0 ]; 120 121 then 122 123 echo "update svn ..." 124 125 svn update 126 127 else 128 129 echo 'checkout from svn...' 130 131 echo "svn checkout --username=${svn-user} --password=${svn_password} ${project_svn_uri}" 132 133 svn checkout --username=$svn_user --password=$svn_password $project_svn_uri 134 135 fi 136 137 138 139 140 141 # ------------------------------------ 142 143 # install maven project 144 145 # ------------------------------------ 146 147 mvn package -Dmaven.test.skip=true -f $svn_full_dir 148 149 # ------------------------------------ 150 151 152 153 echo "copying project to ${deploy_dir}..." 154 155 mkdir -p $deploy_dir 156 157 cp $svn_full_dir/target/$project $deploy_dir -r 158 159 echo "copy project end" 160 161 162 163 echo "docker run --privileged=true -v ${deploy_dir}:/usr/local/tomcat/webapps/${project} -p ${port}:8080 tomcat:7" 164 165 docker run --privileged=true -v $deploy_dir:/usr/local/tomcat/webapps/$project -p $port:8080 tomcat:7tomcat
转载于:https://wwwblogs/dazhidacheng/p/7767511.html
更多推荐
docker菜鸟入门
发布评论