如何使用Okteto在Kubernetes上开发应用程序

news/2024/7/7 16:09:26

The author selected Girls Who Code to receive a donation as part of the Write for DOnations program.

作者选择了《编码的女孩》作为Write for DOnations计划的一部分来接受捐赠。

介绍 (Introduction)

The Okteto CLI is an open-source project that provides a local development experience for applications running on Kubernetes. With it you can write your code on your local IDE and as soon as you save a file, the changes can be pushed to your Kubernetes cluster and your app will immediately update. This whole process happens without the need to build Docker images or apply Kubernetes manifests, which can take considerable time.

Okteto CLI是一个开源项目,可为Kubernetes上运行的应用程序提供本地开发经验。 有了它,您就可以在本地IDE上编写代码,并且一旦保存文件,所做的更改就可以推送到Kubernetes集群,并且您的应用程序将立即更新。 整个过程无需构建Docker映像或应用Kubernetes清单即可完成,这可能会花费大量时间。

In this tutorial, you’ll use Okteto to improve your productivity when developing a Kubernetes-native application. First, you’ll create a Kubernetes cluster and use it to run a standard “Hello World” application. Then you’ll use Okteto to develop and automatically update your application without having to install anything locally.

在本教程中,您将在开发Kubernetes本地应用程序时使用Okteto来提高生产率。 首先,您将创建一个Kubernetes集群,并使用它运行标准的“ Hello World”应用程序。 然后,您将使用Okteto开发并自动更新您的应用程序,而无需在本地安装任何内容。

先决条件 (Prerequisites)

Before you begin this tutorial, you’ll need the following:

在开始本教程之前,您需要满足以下条件:

  • A Kubernetes 1.12+ cluster. In this tutorial, the setup will use a DigitalOcean Kubernetes cluster with three nodes, but you are free to create a cluster using another method.

    Kubernetes 1.12+集群 在本教程中,设置将使用具有三个节点的DigitalOcean Kubernetes集群,但是您可以使用另一种方法自由创建集群 。

  • kubectl and doctl installed and configured to communicate with your cluster.

    安装并配置了kubectldoctl以与您的集群通信。

  • A Docker Hub account

    Docker Hub帐户

  • Docker running on your local machine.

    在本地计算机上运行的Docker 。

第1步-创建Hello World应用程序 (Step 1 — Creating the Hello World Application)

The “Hello World” program is a time-honored tradition in web development. In this case, it is a simple web service that responds “Hello World” to every request. Now that you’ve created your Kubernetes cluster, let’s create a “Hello World” app in Golang and the manifests that you’ll use to deploy it on Kubernetes.

“ Hello World”程序是Web开发中历史悠久的传统。 在这种情况下,它是一个简单的Web服务,它对每个请求都响应“ Hello World”。 现在,您已经创建了Kubernetes集群,让我们在Golang中创建一个“ Hello World”应用程序,并使用清单将其部署到Kubernetes上。

First change to your home directory:

首先更改您的主目录:

  • cd ~

    光盘〜

Now make a new directory called hello_world and move inside it:

现在创建一个名为hello_world的新目录,并在其中移动:

  • mkdir hello_world

    mkdir hello_world
  • cd hello_world

    cd hello_world

Create and open a new file under the name main.go with your favorite IDE or text editor:

使用您喜欢的IDE或文本编辑器以main.go名称创建并打开一个新文件:

  • nano main.go

    纳米main.go

main.go will be a Golang web server that returns the message Hello world!. So, let’s use the following code:

main.go将是一个Golang网络服务器,返回消息Hello world! 。 因此,让我们使用以下代码:

main.go
main.go
package main

import (
    "fmt"
    "net/http"
)

func main() {
    fmt.Println("Starting hello-world server...")
    http.HandleFunc("/", helloServer)
    if err := http.ListenAndServe(":8080", nil); err != nil {
        panic(err)
    }
}

func helloServer(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "Hello world!")
}

The code in main.go does the following:

main.go中的代码执行以下操作:

  • The first statement in a Go source file must be the package name. Executable commands must always use package main.

    Go源文件中的第一条语句必须是package名称。 可执行命令必须始终使用package main

  • The import section indicates which packages the code depends on. In this case it uses fmt for string manipulation, and net/http for the HTTP server.

    import部分指示代码所依赖的软件包。 在这种情况下,它将fmt用于字符串操作,并将net/http用于HTTP服务器。

  • The main function is the entry point to your binary. The http.HandleFunc method is used to configure the server to call the helloServer function when a request to the / path is received. http.ListenAndServe starts an HTTP server that listens on all network interfaces on port 8080.

    main功能是二进制文件的入口。 http.HandleFunc方法用于将服务器配置为在收到对/路径的请求时调用helloServer函数。 http.ListenAndServe启动一个HTTP服务器,该服务器侦听端口8080上的所有网络接口。

  • The helloServer function contains the logic of your request handler. In this case, it will write Hello world! as the response to the request.

    helloServer函数包含请求处理程序的逻辑。 在这种情况下,它将写入Hello world! 作为对请求的响应。

You need to create a Docker image and push it to your Docker registry so that Kubernetes can pull it and then run the application.

您需要创建一个Docker映像并将其推送到Docker注册表中,以便Kubernetes可以将其拉出然后运行该应用程序。

Open a new file under the name Dockerfile with your favorite IDE or text editor:

使用您喜欢的IDE或文本编辑器以Dockerfile的名称打开一个新文件:

  • nano Dockerfile

    纳米Dockerfile

The Dockerfile will contain the commands required to build your application’s Docker container. Let’s use the following code:

Dockerfile将包含构建应用程序的Docker容器所需的命令。 让我们使用以下代码:

Dockerfile
Docker文件
FROM golang:alpine as builder
RUN apk --update --no-cache add bash
WORKDIR /app
ADD . .
RUN go build -o app

FROM alpine as prod
WORKDIR /app
COPY --from=builder /app/app /app/app
EXPOSE 8080
CMD ["./app"]

The Dockerfile contains two stages, builder and prod:

Dockerfile包含两个阶段, builderprod

  • The builder stage contains the Go build tools. It’s responsible for copying the files and building the Go binary.

    builder阶段包含Go构建工具。 它负责复制文件并构建Go二进制文件。

  • The prod stage is the final image. It will contain only a stripped down OS and the application binary.

    prod阶段是最终的形象。 它仅包含精简的操作系统和应用程序二进制文件。

This is a good practice to follow. It makes your production containers smaller and safer since they only contain your application and exactly what is needed to run it.

这是遵循的好习惯。 它使您的生产容器更小,更安全,因为它们只包含您的应用程序以及运行它所需的内容。

Build the container image (replace your_DockerHub_username with your Docker Hub username):

构建容器映像(将your_DockerHub_username替换为Docker Hub用户名):

  • docker build -t your_DockerHub_username/hello-world:latest

    docker build -t your_DockerHub_username / hello-world:latest

Now push it to Docker Hub:

现在将其推送到Docker Hub:

  • docker push your_DockerHub_username/hello-world:latest

    docker push your_DockerHub_username / hello-world:latest

Next, create a new folder for the Kubernetes manifests:

接下来,为Kubernetes清单创建一个新文件夹:

  • mkdir k8s

    mkdir k8s

When you use a Kubernetes manifest, you tell Kubernetes how you want your application to run. This time, you’ll create a deployment object. So, create a new file deployment.yaml with your favorite IDE or text editor:

使用Kubernetes清单时,您告诉Kubernetes您希望应用程序如何运行。 这次,您将创建一个部署对象。 因此,使用您喜欢的IDE或文本编辑器创建一个新文件deployment.yaml

  • nano k8s/deployment.yaml

    纳米k8s / deployment.yaml

The following content describes a Kubernetes deployment object that runs the okteto/hello-world:latest Docker image. Add this content to your new file, but in your case replace okteto listed after the image label with your_DockerHub_username:

以下内容描述了运行okteto/hello-world:latest Docker映像的Kubernetes部署对象。 将此内容添加到新文件中,但在您的情况下,将image标签后列出的okteto替换为your_DockerHub_username

~/hello_world/k8s/deployment.yaml
〜/ hello_world / k8s / deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-world
spec:
  selector:
    matchLabels:
      app: hello-world
  replicas: 1
  template:
    metadata:
      labels:
        app: hello-world
    spec:
      containers:
      - name: hello-world
        image: your_DockerHub_username/hello-world:latest
        ports:
        - containerPort: 8080

The deployment manifest has three main sections:

部署清单包含三个主要部分:

  • metadata defines the name for your deployment.

    metadata定义部署的名称。

  • replicas defines how many copies of it you want running.

    replicas定义了要运行的副本数量。

  • template tells Kubernetes what to deploy, and what labels to add. In this case, a single container, with the okteto/hello-world:latest image, listening on port 8080, and with the app: hello-world label. Note that this label is the same used in the selector section.

    template告诉Kubernetes部署什么以及添加什么标签。 在这种情况下,一个容器具有okteto/hello-world:latest图像,在端口8080上侦听,并具有app: hello-world标签。 请注意,此标签与selector部分中使用的标签相同。

You’ll now need a way to access your application. You can expose an application on Kubernetes by creating a service object. Let’s continue using manifests to do that. Create a new file called service.yaml with your favorite IDE or text editor:

您现在需要一种访问应用程序的方法。 您可以通过创建服务对象在Kubernetes上公开应用程序。 让我们继续使用清单来做到这一点。 使用您最喜欢的IDE或文本编辑器创建一个名为service.yaml的新文件:

  • nano k8s/service.yaml

    纳米k8s / service.yaml

The following content describes a service that exposes the hello-world deployment object, which under the hood will use a DigitalOcean Load Balancer:

以下内容描述了公开hello-world部署对象的服务,该服务在幕后将使用DigitalOcean负载均衡器:

k8s/service.yaml
k8s / service.yaml
apiVersion: v1
kind: Service
metadata:
  name: hello-world
spec:
  type: LoadBalancer
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
      name: http
  selector:
    app: hello-world

The service manifest has four main sections:

服务清单包含四个主要部分:

  • metadata tells Kubernetes how to name your service.

    metadata告诉Kubernetes如何命名您的服务。

  • type tells Kubernetes how you want to expose your service. In this case, it will expose it externally through a Digital Ocean Load Balancer.

    type告诉Kubernetes您如何公开服务。 在这种情况下,它将通过Digital Ocean Load Balancer在外部公开它。

  • The ports label tells Kubernetes which ports you want to expose, and how to map them to your deployment. In this case, you will expose port 80 externally and direct it to port 8080 in your deployment.

    ports标签告诉Kubernetes您要公开哪些端口,以及如何将它们映射到您的部署。 在这种情况下,您将在外部公开端口80 ,并将其定向到部署中的端口8080

  • selector tells Kubernetes how to direct traffic. In this case, any pod with the app: hello-world label will receive traffic.

    selector告诉Kubernetes如何引导流量。 在这种情况下,任何带有app: hello-world标签的pod都会收到流量。

You now have everything ready to deploy your “Hello World” application on Kubernetes. We will do this next.

现在,您已准备就绪,可以在Kubernetes上部署“ Hello World”应用程序了。 接下来,我们将进行此操作。

第2步-部署Hello World应用程序 (Step 2 — Deploying Your Hello World Application)

In this step you’ll deploy your “Hello World” application on Kubernetes, and then you’ll validate that it is working correctly.

在这一步中,您将在Kubernetes上部署“ Hello World”应用程序,然后验证其是否正常运行。

Start by deploying your application on Kubernetes:

首先在Kubernetes上部署您的应用程序:

  • kubectl apply -f k8s

    kubectl适用-f k8s

You’ll see the following output:

您将看到以下输出:


   
Output
deployment.apps "hello-world" created service "hello-world" created

After about one minute or so, you will be able to retrieve your application’s IP. Use this kubectl command to check your service:

大约一分钟后,您将可以检索应用程序的IP。 使用此kubectl命令检查您的服务:

  • kubectl get service hello-world

    kubectl获取服务世界

You’ll see an output like this listing your Kubernetes service objects. Note your application’s IP in the the EXTERNAL-IP column:

您将看到类似这样的输出,其中列出了您的Kubernetes服务对象。 在EXTERNAL-IP列中记下应用程序的IP:


   
Output
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE hello-world ClusterIP your_cluster_ip your_external_ip 8080/TCP 37s

Open your browser and go to your_external_ip listed for your “Hello World” application. Confirm that your application is up and running before continuing with the next step.

打开浏览器,然后转到“ Hello World”应用程序列出的your_external_ip 。 在继续下一步之前,请确认您的应用程序已启动并正在运行。

Until this moment, you’ve followed a fairly traditional pathway for developing applications with Kubernetes. Moving forward, whenever you want to change the code in your application, you’ll have to build and push a new Docker image, and then pull that image from Kubernetes. This process can take quite some time. Okteto was designed to streamline this development inner-loop. Let’s look at the Okteto CLI and see just how it can help.

到目前为止,您已经遵循了使用Kubernetes开发应用程序的相当传统的途径。 展望未来,每当要更改应用程序中的代码时,都必须构建并推送一个新的Docker映像,然后从Kubernetes中提取该映像。 此过程可能会花费一些时间。 Okteto旨在简化此开发内部循环。 让我们看一下Okteto CLI,看看它如何提供帮助。

步骤3 —安装Okteto CLI (Step 3 — Installing the Okteto CLI)

You will now improve your Kubernetes development productivity by installing the Okteto CLI. The Okteto command line interface is an open-source project that lets you synchronize application code changes to an application running on Kubernetes. You can continue using your favorite IDE, debuggers, or compilers without having to commit, build, push, or redeploy containers to test your application–as you did in the previous steps.

现在,您将通过安装Okteto CLI来提高Kubernetes的开发效率。 Okteto命令行界面是一个开源项目,可让您将应用程序代码更改同步到Kubernetes上运行的应用程序。 您可以继续使用自己喜欢的IDE,调试器或编译器,而无需提交,生成,推送或重新部署容器来测试您的应用程序,就像在前面的步骤中所做的那样。

To install the Okteto CLI on a macOS or Linux machine, run the following command:

要在macOS或Linux计算机上安装Okteto CLI,请运行以下命令:

  • curl https://get.okteto.com -sSfL | sh

    curl https://get.okteto.com -sSfL | SH

Let’s take a closer look at this command:

让我们仔细看看以下命令:

  • The curl command is used to transfer data to and from a server.

    curl命令用于在服务器之间传输数据。

  • The -s flag suppresses any output.

    -s标志禁止任何输出。

  • The -S flag shows errors.

    -S标志显示错误。

  • The -f flag causes the request to fail on HTTP errors.

    -f标志导致请求因HTTP错误而失败。

  • The -L flag makes the request follow redirects.

    -L标志使请求遵循重定向。

  • The | operator pipes this output to the sh command, which will download and install the latest okteto binary in your local machine.

    | 操作员将此输出传递给sh命令,该命令将在本地计算机上下载并安装最新的okteto二进制文件。

If you are running Windows, you can alternately download the file through your web browser and manually add it to your $PATH.

如果您正在运行Windows,则可以通过Web浏览器交替下载文件,然后将其手动添加到$PATH

Once the Okteto CLI is installed, you are ready to put your “Hello World” application in development mode.

安装Okteto CLI后,就可以将“ Hello World”应用程序置于开发模式了。

步骤4 —将Hello World应用程序置于开发模式 (Step 4 — Putting Your Hello World Application in Development Mode)

The Okteto CLI is designed to swap the application running on a Kubernetes cluster with the code you have in your machine. To do so, Okteto uses the information provided from an Okteto manifest file. This file declares the Kubernetes deployment object that will swap with your local code.

Okteto CLI旨在将Kubernetes集群上运行的应用程序与您计算机中的代码交换。 为此,Oktoto使用从Okteto清单文件提供的信息。 该文件声明了将与您的本地代码交换的Kubernetes部署对象。

Create a new file called okteto.yaml with your favorite IDE or text editor:

使用您喜欢的IDE或文本编辑器创建一个名为okteto.yaml的新文件:

  • nano okteto.yaml

    纳米okteto.yaml

Let’s write a basic manifest where you define the deployment object name, the Docker base image to use, and a shell. We will return to this information later. Use the following sample content file:

让我们写一个基本清单,在其中定义部署对象名称,要使用的Docker基本映像以及一个外壳。 我们稍后将返回此信息。 使用以下示例内容文件:

okteto.yaml
okteto.yaml
name: hello-world
image: okteto/golang:1
workdir: /app
command: ["bash"]

Prepare to put your application in development mode by running the following command:

通过运行以下命令,准备将您的应用程序置于开发模式:

  • okteto up

    奥克托

   
Output
✓ Development environment activated ✓ Files synchronized Namespace: default Name: hello-world Welcome to your development environment. Happy coding! default:hello-world /app>

The okteto up command swaps the “Hello World” application into a development environment, which means:

okteto up命令将“ Hello World”应用程序交换到开发环境中,这意味着:

  • The Hello World application container is updated with the docker image okteto/golang:1. This image contains the required dev tools to build, test, debug, and run the “Hello World” application.

    Hello World应用程序容器已使用okteto/golang:1 image okteto/golang:1 。 该映像包含构建,测试,调试和运行“ Hello World”应用程序所需的开发工具。

  • A file synchronization service is created to keep your changes up-to-date between your local filesystem and your application pods.

    创建文件同步服务以使您的更改在本地文件系统和应用程序Pod之间保持最新状态。

  • A remote shell starts in your development environment. Now you can build, test, and run your application as if you were in your local machine.

    远程外壳程序将在您的开发环境中启动。 现在,您可以像在本地计算机上一样构建,测试和运行应用程序。

  • Whatever process you run in the remote shell will get the same incoming traffic, the same environment variables, volumes, or secrets as the original “Hello World” application pods. This, in turn, gives you a highly realistic, production-like development environment.

    无论您在远程Shell中运行什么进程,都将获得与原始“ Hello World”应用程序容器相同的传入流量,相同的环境变量,卷或机密信息。 反过来,这为您提供了高度现实的,类似于生产的开发环境。

In the same console, now run the application as you would typically do (without building and pushing a Docker image), like this:

在同一控制台中,现在像平常一样运行应用程序(无需构建和推送Docker映像),如下所示:

  • go run main.go

    去运行main.go

   
Output
Starting hello-world server...

The first time you run the application, Go will download your dependencies and compile your application. Wait for this process to finish and test your application by opening your browser and refreshing the page of your application, just as you did previously.

第一次运行该应用程序时,Go会下载您的依赖项并编译您的应用程序。 与以前一样,通过打开浏览器并刷新应用程序页面来等待此过程完成并测试您的应用程序。

Now you are ready to begin developing directly on Kubernetes.

现在,您可以开始直接在Kubernetes上进行开发了。

步骤5 —直接在Kubernetes上进行开发 (Step 5 — Developing Directly on Kubernetes)

Let’s start making changes to the “Hello World” application and then see how these changes get reflected in Kubernetes.

让我们开始对“ Hello World”应用程序进行更改,然后看看这些更改如何在Kubernetes中得到体现。

Open the main.go file with your favorite IDE or text editor. For example, open a separate console and run the following command:

使用您最喜欢的IDE或文本编辑器打开main.go文件。 例如,打开一个单独的控制台并运行以下命令:

  • nano main.go

    纳米main.go

Then, change your response message to Hello world from DigitalOcean!:

然后,将您的响应消息Hello world from DigitalOcean!更改为Hello world from DigitalOcean!

main.go
main.go
package main

import (
    "fmt"
    "net/http"
)

func main() {
    fmt.Println("Starting hello-world server...")
    http.HandleFunc("/", helloServer)
    if err := http.ListenAndServe(":8080", nil); err != nil {
        panic(err)
    }
}

func helloServer(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "Hello world from DigitalOcean!")
}

It is here that your workflow changes. Instead of building images and redeploying containers to update the “Hello World” application, Okteto will synchronize your changes to your development environment on Kubernetes.

工作流就是在这里更改的。 Okteto无需构建映像和重新部署容器来更新“ Hello World”应用程序,而是将您的更改同步到Kubernetes上的开发环境。

From the console where you executed the okteto up command, cancel the execution of go run main.go by pressing CTRL + C. Now rerun the application:

在执行okteto up命令的控制台中,按CTRL + C取消执行go run main.go 。 现在重新运行该应用程序:

  • default:hello-world /app> go run main.go

    默认值:hello-world / app>运行main.go

   
Output
Starting hello-world server...

Go back to the browser and reload the page for your “Hello World” application.

返回浏览器并重新加载“ Hello World”应用程序的页面。

Your code changes were applied instantly to Kubernetes, and all without requiring any commits, builds, or pushes.

您的代码更改被立即应用到Kubernetes,而所有这些都不需要进行任何提交,构建或推送。

结论 (Conclusion)

Okteto transforms your Kubernetes cluster into a fully-featured development platform with the click of a button. In this tutorial you installed and configured the Okteto CLI to iterate your code changes directly on Kubernetes as fast as you can type code. Now you can head over to the Okteto samples repository to see how to use Okteto with different programming languages and debuggers.

只需单击一下按钮, Okteto即可将您的Kubernetes集群转变为功能全面的开发平台。 在本教程中,您安装并配置了Okteto CLI,使其可以在Kubernetes上直接快速键入代码更改。 现在,您可以转到Okteto示例存储库,以了解如何在不同的编程语言和调试器中使用Okteto。

Also, if you share a Kubernetes cluster with your team, consider giving each member access to a secure Kubernetes namespace, configured to be isolated from other developers working on the same cluster. This great functionality is also provided by the Okteto App in the DigitalOcean Kubernetes Marketplace.

另外,如果您与团队共享一个Kubernetes集群,请考虑为每个成员授予安全的Kubernetes命名空间的访问权限,该命名空间配置为与在同一集群上工作的其他开发人员隔离。 Okteto应用程序还在DigitalOcean Kubernetes市场中提供了此强大功能。

翻译自: https://www.digitalocean.com/community/tutorials/how-to-develop-applications-on-kubernetes-with-okteto


http://www.niftyadmin.cn/n/3648144.html

相关文章

解决radio被选中,但是重复点击后事件不触发的问题

网上找了好多帖子&#xff0c;都没用&#xff0c;在百度知道发现以下答案 知识点&#xff1a;使用 jq的prop才能设置 html $(.ss).click(function(){$(this).find("input[typeradio]").attr("checked",true);});<ul><li class"ss">…

[Python]RSS处理资源集合

随时更新。技巧&#xff1a;使用 Universal Feed Parser 驾驭 RSS Universal Feed Parser 是一个下载和解析连锁消息包的 Python 模块。它可以处理 RSS 0.90、Netscape RSS 0.91、Userland RSS 0.91、RSS 0.92、RSS 0.93、RSS 0.94、RSS 1.0、RSS 2.0、Atom 和 CDF 消息包。我…

我评闫辉的《程序员,建立你的商业意识》

我也是老程序员&#xff0c;也把闫辉的文章从头到尾仔细读过了。做一个点评&#xff1a; 1&#xff1a;每个成功的技术人士都有很多资源可以共享出来&#xff0c;换句话说&#xff0c;每一个成功人士的背后都有一套成功哲学。而闫辉记者又恰恰以比我们这些技术人大得多的频率采…

map中放数组,遍历_如何使用.map()遍历JavaScript中的数组项

map中放数组,遍历介绍 (Introduction) From the classic forloop to the forEach() method, various techniques and methods are used to iterate through datasets in JavaScript. One of the most popular methods is the .map() method. .map() creates an array from call…

分布式开源调度框架TBSchedule详解

主要内容&#xff1a;第一部分 TBSchedule基本概念及原理 1. 概念介绍 2. 工作原理 3. 源码分析 4. 与其他开源调度框架对比第二部分 TBSchedule分布式调度示例 1. TBSchedule源码下载 2. 引入源码Demo开发示例 3. 控制台配置任务调度 4. selectTasks方法参数说…

如何打组合竞争力的牌

by zhengyun_ustc 20060712本期《人力资本》就“组合竞争力”洋洋洒洒了三页纸&#xff0c;举的最招人的例子就是徐静蕾&#xff0c;演员/导演/歌手/博客&#xff0c;每一个单拎出来她都不是最强的&#xff0c;但是你必须承认老徐是大红人而且还招人待见&#xff0c;为什么呢&a…

如何让我们在Ubuntu 20.04上加密来保护Nginx

介绍 (Introduction) Let’s Encrypt is a Certificate Authority (CA) that provides an easy way to obtain and install free TLS/SSL certificates, thereby enabling encrypted HTTPS on web servers. It simplifies the process by providing a software client, Certbot…

Docker基本概念详解

本文只是对Docker的概念做了较为详细的介绍&#xff0c;并不涉及一些像Docker环境的安装以及Docker的一些常见操作和命令。阅读本文大概需要15分钟&#xff0c;通过阅读本文你将知道一下概念&#xff1a;容器什么是Docker&#xff1f;Docker思想、特点Docker容器主要解决什么问…