自上一次使用docker还是在大学学习的时候,那个时候作者也写过docker的几篇教程,但是质量非常烂,例如:
windows 10环境用docker 发布springboot项目
不过,后来我就没怎么碰过docker了,可是最近这份工作因为公司里从开发到生产环境都在用docker,所以我又得重新捡起这个技能。这次我打算写一篇关于docker的入门教程,希望能跟大家一起学习进步!
首先,咱们得了解一下什么是docker。它其实就是一种开源的平台,用来自动部署、管理、扩展和运行各种应用程序的技术。它允许开发人员把他们编写的应用程序和相关的依赖库,全都封装到一个叫做"容器"的小家伙里面,然后就能在任何只要装了Docker的环境里跑这个应用!Docker有很多牛逼的功能,例如流畅的跨平台兼容性、严格的资源隔离、精确的版本控制以及超高的资源利用率等等!
例如在java微服务的开发过程中,我们要新增这个微服务的节点,如果没用docker,我们是不是要把jar包上传到服务器,然后再把它启动起来,一套流程下来很麻烦,但是你用了docker配合k8s之后,你只需要点一个加号键,就新增了一个节点(pod),点两次就新增了两个,就像这样:
包括之前请教运维同事也是,作者同样惊讶到了
牛的还在后面,这次我们先不讲,后面慢慢讲。
接下来,科普一些Docker的背景知识,首先,docker之所以能诞生,主要是因为传统的应用部署方式面临着以下几个难题:
- 旧有的应用部署手段:时间回到Docker刚刚面世的那会儿,应用程序的部署往往依赖于特定的操作系统环境配置和依赖项。然而,这种依赖性容易引发各种不统一的问题,无论是开发环境和生产环境之间的差异,还是依赖项之间的冲突,都可能造成应用程序在别的环境下“水土不服”,无法好好运转。
- 传统虚拟化技术的短板:以前我们常用的虚拟化技术,比如说VMWare或者VirtualBox,虽然能在一台物理机器上跑出好几个虚拟机,每个虚拟机都有自己独立的操作系统。但是,虚拟机通常比较重,启动和运行都要消耗大量的资源,导致性能损耗严重。
- 微服务架构的崛起:近年来,微服务架构逐渐成为了主流,应用程序被拆分成了许多个独立的小服务。而这些小服务则需要在各种各样的环境中快速进行部署和伸缩。如果还是采用传统的部署方式,就很难满足微服务灵活性和扩展性的要求了。
Docker 于 2013 年由 Solomon Hykes 和他的团队在 dotCloud(现为 Docker Inc.)开发并开源。它基于 Linux 容器技术(如 LXC),但通过 Docker 提供了一个简单易用的界面,允许开发者轻松创建、部署和管理容器。Docker 容器使用共享操作系统内核的方式,比虚拟机更加轻量级,占用的资源更少,同时也更容易实现跨平台部署。
Docker 的诞生和普及,为应用程序的开发、测试、部署和运维带来了巨大的变革,使得“在我的机器上可以正常工作”的问题变得不再棘手,从而推动了 DevOps 和 CI/CD(持续集成/持续交付)实践的发展。
镜像和容器
说了这么多,这里先跟大家举个例子,在java中,我们是这么写代码创建一个对象的:
Student student = new Student();
这里,Student 类就像是 Docker 中的一个镜像,而 new Student() 则是根据这个镜像创建的一个容器实例。具体来说:
类(Class):类似于 Docker 镜像,它定义了对象的结构和行为。
对象(Object):类似于 Docker 容器,它是类的一个实例,具有具体的属性值和行为。
这是我们的Student类
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public void introduce() {
System.out.println("Hello, my name is " + name + " and I am " + age + " years old.");
}
}
public class Main {
public static void main(String[] args) {
Student student = new Student("Alice", 20);
student.introduce();
}
}
在这个例子中:
Student 类定义了学生对象的属性(name 和 age)和行为(introduce 方法)。
new Student(“Alice”, 20) 创建了一个具体的 Student 对象实例。
现在我们假设有一个 Docker 镜像,名为 my-app-image,它包含了我们的 Java 应用程序和所有依赖项
# 构建 Docker 镜像
docker build -t my-app-image .
# 运行 Docker 容器
docker run -it --rm --name my-running-container my-app-image
在这个例子中:
my-app-image 类似于 Student 类,它定义了应用程序的配置和内容。
docker run 命令创建了一个容器实例,类似于 new Student(“Alice”, 20)。
通过这个例子大家就知道了docker里面有两个概念:镜像和容器
举个更实际的例子,假设你有一个开发环境,已经用 Docker 创建了一个基于 nginx
镜像的容器,这个容器负责提供 Web 服务。你可能会对容器进行一些定制,比如修改配置文件,添加一些静态资源。然后,你可以通过提交这些更改创建一个新的镜像。这就像是在原有的 Nginx 配置模板(镜像)基础上,创建了一个新的、包含你定制内容的模板(新的镜像)。接下来,你可以使用这个新镜像创建多个容器实例,这些实例都运行相同的 Web 服务,并且具备你定制的配置。
就拿我们java开发中打包jar包一样,每次打出来的包就是一个镜像,而跑起来这个进程就是一个容器,而我们上面举的一个按键就可以添加一个节点,大家也可以把他简单理解为新加了一个容器。
仓库
这个时候我们再引入一个概念:仓库,仓库是 Docker 生态系统的一部分,它提供了一种方便地共享和分发镜像的方式。一个典型的仓库,比如 Docker Hub,由一个中心服务器和一个网络存储库组成。用户可以在中心服务器上注册自己的账户并上传自己的镜像。然后,其他人可以使用这个镜像,并将其下载到他们的本地环境中。这种机制可以帮助用户快速、方便地获取和使用各种开源镜像。
所以在 Java 开发中,我们也可以把 jar 包上传到一个仓库,然后其他人可以下载这个 jar 包,并将其导入到他们的项目中。这样,我们就可以方便地共享和分发我们的代码和资源。就像作者之前提到的中央仓库一样:
如何发布jar包到maven中央仓库(2024年3月最新版保姆级教程)
java开发中需要用到的jar包可以上传到maven中央仓库,其他开发者可以直接访问maven中央仓库获取这个jar包,然后导入到他们的项目中。例如,对于上面所说的容器定制,你可以使用 Docker Hub 上的各种开源镜像,这些镜像可以直接用于创建容器实例或者定制镜像。
别bb,来个总结:
镜像就像是一个应用程序的“模板”。它包含了运行应用所需的一切,比如操作系统、库和应用代码。你可以把它想象成一个打包好的应用快照,随时可以用来创建容器。
容器是镜像的实际运行实例。你可以把它当成是根据模板(镜像)生产出来的一个具体的产品。容器是轻量级的,启动速度快,而且每个容器都有自己独立的运行环境。比如,你可以用同一个镜像启动多个容器,每个容器里跑的应用都是独立的。
仓库是用来存储和共享镜像的地方。你可以把它理解为一个镜像的“库”,在这里你可以找到别人上传的镜像,也可以把自己创建的镜像上传到这里。Docker Hub 是最常用的公共仓库,但你也可以设置自己的私有仓库。