一、docker介绍
为什么要使用docker
云计算时代的挑战
在计算机技术发展的早期,几乎所有的程序都是在开发后部署到一台或是少数几台服务器上的。那时的程序也几乎都是集所有模块和运行时环境为一身的“全栈应用”,虽然这些程序可以基于一套良好、完善的协议栈 ( 譬如一套完整的 MVC 架构 ) 进行开发,但再好的架构也无法让应用服务在这种体系下快速发展。
随着互联网的极速发展,应用程序的功能越来越丰富,而需要迭代的速度要求也越来越高,为了实现这些目标,应用的开发逐渐趋向服务化甚至微服务化。每个应用程序都有其对应依赖的操作系统或者其他程序,而在将应用程序细分为不同的微服务或者是其他形式的微小应用模块后,解决这种依赖问题会愈发显得棘手。有的应用运行环境特别复杂,搭建过程也极易出错,这都是让开发、测试、运维人员焦头烂额的地方。更多时候,开发者们肯定更愿意将他们宝贵的时间用在实际的开发中,而不是纠缠着应用运行环境的问题上。

同时,由于物理硬件的更新迭代速度已经难以追赶互联网的脚步,应用的部署逐渐转向集群化。应用模块的数量乘上每个应用所部署的机器的数量,会是一个非常庞大的数字。相信所有的开发或者运维都不会愿意把时间浪费在逐一搭建服务器环境这种重复的劳动上。
这些变化都对应用的开发、部署带来了不小的挑战。
我想很多读者已经想到了应对这些挑战的办法了,没错,那就是虚拟化技术。通过虚拟化技术可以让环境的搭建变得更加的容易,对我们快速部署分布式应用服务体系提供了极大的便利。
进而言之,如果我们把管理环境的复杂度,更轻量级的虚拟化实现等更加实际的问题考虑进去,容器技术自然成了虚拟化技术中最佳的选择项。
皆为效率
如果说在分布式部署中应用容器技术是一个方向,那么 Docker 就是在这个方向上跑得最快也最完美的运动员了。Docker 不论从实现容器技术的完整性上来说,还是从上手易用性来说,都是可圈可点的。
好了,这里我要穿插一下推荐 Docker 的原因了。我们使用 Docker 的目的其实很简单,就是利用它的全面性和易用性来提升我们的工作效率。了解了这个目的,我想大家会更容易理解很多场合 Docker 能派上用场的原因。当然,通过这个道理,你也就明白了为什么我会说 Docker 是一门新时代开发者必须掌握的技术了。毕竟所有的老板都希望找到会得多、干活快的优秀开发者 ( 亦或者说,会的多、干活快是优秀开发者所必备的品质 )。
再怎么从理论上说快也是很难服众的,是骡子是马拉出来“跑个分”就知道了。Docker 官方对 Docker 在工作上带来的提升做了调查研究,分别从工作效率的提升和技术设计投入的减少等方面数据化了 Docker 所做出的突出贡献。

Docker 的理念
让我们先来从一张 Docker 官方提供的架构图来看看 Docker 对容器结构的设计。

举个具体的例子,在常见的虚拟机实现中,我们要搭建一套 LAMP 结构的服务,我们通常会建立一个虚拟机,在虚拟机中安装上 Linux 系统,之后分别安装 Apache、MySQL 和 PHP。而在 Docker 里,最佳的实践是分别基于 Apache、MySQL 和 PHP 的镜像建立三个容器,分别运行 Apache、MySQL 和 PHP ,而它们所在的虚拟操作系统也直接共享于宿主机的操作系统。 如果我们将 Docker 的轻量级容器实现和虚拟机的一些参数进行对比,更容易得到结果。
| 属性 | Docker | 虚拟机 |
|---|---|---|
| 启动速度 | 秒级 | 分钟级 |
| 硬盘使用 | MB 级 | GB级 |
| 性能 | 接近原生 | 较低 |
| 普通机器支撑量 | 数百个 | 几个 |
虽然这里只列出了一些 Docker的优势项,但这些优势都是对我们开发中环境搭建和使用极其有帮助的内容。就拿启动速度来说,我们在开发中显然不愿意调整环境或更新代码后要等待几分钟来让其生效,Docker 秒级的启动速度几乎让我们感知不到我们对环境做了什么改动。而像虚拟机占用大量操作系统资源,导致我们本地开发使用电脑过慢 ( 有时候不得不将环境搭建在另外的机器上,但这显然在代码编写到运行自测的过程中增加很多工作量 ) 等问题,也容易得到解决。
我们能用 Docker 做些什么
从理论上我们已经知道 Docker 能够为我们的工作带来巨大的便利,那么将其放于实践中,我们应该如何正确的使用它呢?这里我摘录整理了一段来自 Docker 官方文档的指导意见,希望能够对大家的实践提供参考。
更快、更一致的交付你的应用程序
使用 Docker 后,开发者能够在本地容器中得到一套标准的应用或服务的运行环境,由此可以简化开发的生命周期 ( 减少在不同环境间进行适配、调整所造成的额外消耗 )。对于整个应用迭代来说,加入 Docker 的工作流程将更加适合持续集成 ( Continuous Integration ) 和持续交付 ( Continuous Delivery )。
举个具体的例子:
- 开发者能够使用 Docker 在本地编写代码并通过容器与其他同事共享他们的工作。
- 他们能够使用 Docker 将编写好的程序推送至测试环境进行自动化测试或是人工测试。
- 当出现 Bug 时,开发者可以在开发环境中修复它们,并很快的重新部署到测试环境中。
- 在测试完成后,部署装有应用程序的镜像就能完成生产环境的发布。
跨平台部署和动态伸缩
基于容器技术的 Docker 拥有很高的跨平台性,Docker 的容器能够很轻松的运行在开发者本地的电脑,数据中心的物理机或虚拟机,云服务商提供的云服务器,甚至是混合环境中。
同时,Docker 的轻量性和高可移植性能够很好的帮助我们完成应用的动态伸缩,我们可以通过一些手段近实时的对基于 Docker 运行的应用进行弹性伸缩,这能够大幅提高应用的健壮性。
让同样的硬件提供更多的产出能力
Docker 的高效和轻量等特征,为替代基于 Hypervisor 的虚拟机提供了一个经济、高效、可行的方案。在 Docker 下,你能节约出更多的资源投入到业务中去,让应用程序产生更高的效益。同时,如此低的资源消耗也说明了 Docker 非常适合在高密度的中小型部署场景中使用。
了解 Docker 的核心组成
在 Docker 体系里,有四个对象 ( Object ) 是我们不得不进行介绍的,因为几乎所有 Docker 以及周边生态的功能,都是围绕着它们所展开的。它们分别是:镜像 ( Image )、容器 ( Container )、网络 ( Network )、数据卷 ( Volume )。
镜像
镜像 ( Image ) 这个概念相信大家不会陌生,因为它是其他虚拟化技术 ( 特别是虚拟机 ) 中常常被使用的一个概念。所谓镜像,可以理解为一个只读的文件包,其中包含了虚拟环境运行最原始文件系统的内容。
当然,Docker 的镜像与虚拟机中的镜像还是有一定区别的。首先,之前我们谈到了 Docker 中的一个创新是利用了 AUFS(参考文档:www.cnblogs.com/sammyliu/p/… 作为底层文件系统实现,通过这种方式,Docker 实现了一种增量式的镜像结构。

另外,由于这种结构,Docker 的镜像实质上是无法被修改的,因为所有对镜像的修改只会产生新的镜像,而不是更新原有的镜像。
容器
容器 ( Container ) 就更好理解了,在容器技术中,容器就是用来隔离虚拟环境的基础设施,而在 Docker 里,它也被引申为隔离出来的虚拟环境。
如果把镜像理解为编程中的类,那么容器就可以理解为类的实例。镜像内存放的是不可变化的东西,当以它们为基础的容器启动后,容器内也就成为了一个“活”的空间。
用更官方的定义,Docker 的容器应该有三项内容组成:
- 一个 Docker 镜像
- 一个程序运行环境
- 一个指令集合
网络
对于大部分程序来说,它们的运行都不会是孤立的,而是要与外界或者更准确的说是与其他程序进行交互的,这里的交互绝大多数情况下指的就是数据信息的交换。网络通讯是目前最常用的一种程序间的数据交换方式了。
由于计算机网络领域拥有相对统一且独立的协议等约定,其跨平台性非常优秀,所有的应用都可以通过网络在不同的硬件平台或操作系统平台上进行数据交互。特别是在分布式云计算的时代,应用或服务间的通讯更是充分依赖于网络传输,所以自然拥有一套完善的网络体系支撑,是承载应用运行所必须的基础设施。
在 Docker 中,实现了强大的网络功能,我们不但能够十分轻松的对每个容器的网络进行配置,还能在容器间建立虚拟网络,将数个容器包裹其中,同时与其他网络环境隔离。

另外,利用一些技术,Docker 能够在容器中营造独立的域名解析环境,这使得我们可以在不修改代码和配置的前提下直接迁移容器,Docker 会为我们完成新环境的网络适配。对于这个功能,我们甚至能够在不同的物理服务器间实现,让处在两台物理机上的两个 Docker 所提供的容器,加入到同一个虚拟网络中,形成完全屏蔽硬件的效果。
正是因为拥有强大的网络功能,才能让我们制造健壮的 Docker 应用体系。
数据卷
除了网络之外,文件也是重要的进行数据交互的资源。在以往的虚拟机中,我们通常直接采用虚拟机的文件系统作为应用数据等文件的存储位置。然而这种方式其实并非完全安全的,当虚拟机或者容器出现问题导致文件系统无法使用时,虽然我们可以很快的通过镜像重置文件系统使得应用快速恢复运行,但是之前存放的数据也就消失了。
为了保证数据的独立性,我们通常会单独挂载一个文件系统来存放数据。这种操作在虚拟机中是繁琐的,因为我们不但要搞定挂载在不同宿主机中实现的方法,还要考虑挂载文件系统兼容性,虚拟操作系统配置等问题。值得庆幸的是,这些在 Docker 里都已经为我们轻松的实现了,我们只需要简单的一两个命令或参数,就能完成文件系统目录的挂载。
能够这么简单的实现挂载,主要还是得益于 Docker 底层的 Union File System 技术。在 UnionFS 的加持下,除了能够从宿主操作系统中挂载目录外,还能够建立独立的目录持久存放数据,或者在容器间共享。
在 Docker 中,通过这几种方式进行数据共享或持久化的文件或目录,我们都称为数据卷 ( Volume )。
Docker Engine
时至今日,Docker 生态已经远比它诞生之初要庞大许多,虽然我们仍然习惯使用 Docker 这个名字去指代实现容器技术支持的软件,但显然更加容易与其他的概念产生混淆。这里我们很有必要对这个 Docker 中最核心的软件进行介绍,不仅因为它在 Docker 生态中扮演着中心的地位,也因为它是我们在开发中实实在在接触最多的东西。
目前这款实现容器化的工具是由 Docker 官方进行维护的,Docker 官方将其命名为 Docker Engine,同时定义其为工业级的容器引擎 ( Industry-standard Container Engine )。在 Docker Engine 中,实现了 Docker 技术中最核心的部分,也就是容器引擎这一部分。
docker daemon 和 docker CLI 虽然我们说 Docker Engine 是一款软件,但实实在在去深究的话,它其实算是由多个独立软件所组成的软件包。在这些程序中,最核心的就是 docker daemon 和 docker CLI 这俩了。
所有我们通常认为的 Docker 所能提供的容器管理、应用编排、镜像分发等功能,都集中在了 docker daemon 中,而我们之前所提到的镜像模块、容器模块、数据卷模块和网络模块也都实现在其中。在操作系统里,docker daemon 通常以服务的形式运行以便静默的提供这些功能,所以我们也通常称之为 Docker 服务。

通常来说,我们是采用在控制台或者命令行输入命令来控制 docker daemon 的,因为这样很酷也更容易适应那些有或者没有图形界面的操作系统。
那么问题来了,如果我们在控制台中编写一个 HTTP 请求以借助 docker daemon 提供的 RESTful API 来操控它,那显然是个费脑、费手又费时间的活儿。所以在 Docker Engine 里还直接附带了 docker CLI 这个控制台程序。

四、使用Dockerfile创建镜像
Dockerfile的结构
总体上来说,我们可以将 Dockerfile 理解为一个由上往下执行指令的脚本文件。当我们调用构建命令让 Docker 通过我们给出的 Dockerfile 构建镜像时,Docker 会逐一按顺序解析 Dockerfile 中的指令,并根据它们不同的含义执行不同的操作。
如果进行细分,我们可以将 Dockerfile 的指令简单分为五大类。
- 基础指令:用于定义新镜像的基础和性质。
- 控制指令:是指导镜像构建的核心部分,用于描述镜像在构建过程中需要执行的命令。
- 引入指令:用于将外部文件直接引入到构建镜像内部。
- 执行指令:能够为基于镜像所创建的容器,指定在启动时需要执行的脚本或命令。
- 配置指令:对镜像以及基于镜像所创建的容器,可以通过配置指令对其网络、用户等内容进行配置。
这五类命令并非都会出现在一个 Dockerfile 里,但却对基于这个 Dockerfile 所构建镜像形成不同的影响。

五、使用 Docker Compose 管理容器
六、安装gitlab
- 拉取gitlab镜像并启动:
docker pull gitlab/gitlab-ce
sudo docker run --detach \
--hostname fhero.me \
--publish 443:443 --publish 80:80 --publish 22:22 \
--name gitlab \
--restart always \
--volume ~/gitlab/config:/etc/gitlab \
--volume ~/gitlab/logs:/var/log/gitlab \
--volume ~/gitlab/data:/var/opt/gitlab \
gitlab/gitlab-ce:latest
因为部署在本地,又指定了fhero.me作为域名,所以在/etc/hosts配置下,这样可以通过域名访问gitlab。
七、安装Jenkins:
docker run \
-u root \
--rm \
-d \
-p 8081:8080 \
-v jenkins-data:/var/jenkins_home \
-v /var/run/docker.sock:/var/run/docker.sock \
jenkinsci/blueocean
- d:后台运行(守护进程)
- -p 8081:8080 是指定对外暴露的端口,容器内部用8080对应外部的80801
- -v jenkins-data:/var/jenkins_home 是将jenkins挂载到jenkins-data下,方便看,并且空间也大
安装成功之后,访问ip+端口号(8081)
这里需要输入管理员密码(这个密码找了好久,虽然在网上看了很多博客,但是对容器的理解的不是太透彻)
这里推荐进入到容器里面去找
- 查看当前正在运行的容器(docker ps)
- docker exec -it 1215fds7ga744 /bin/bash
- cd /var/jenkins/secrets/initialAdminPassword

Jenkins新建项目中源码管理使用Git时遇到如下问题: Failed to connect to repository : Error performing command: git ls-remote -h …. 需要查看服务器上是否已经安装git.
- 1、git version
- 2、whereis git 如果没有git,此时需要安装git, #yum install git 打开jenkins主页面–>系统管理–>全局工具配置 在git一栏中name使用git即可,Path to Git executable 中填写git的地址,(即whereis git的结果) 保存即可.


从起启动Jenkins时输入之前的用户名和密码,竟然提示我无效的用户名或密码,最后只能用强攻了,将用户名和密码去掉,直接进入到Jenkins。

swam创建集群:mp.weixin.qq.com/s/cKRAs-H8p…?