在这篇文章中,我们将看到一些东西:

  • 使用容器
  • 码头工人组成
  • 建筑图像
    • 多阶段构建
  • 卷数
  • ARG使我们的形象更加灵活
  • 入口点
  • Docker集线器和容器注册表
  • 资料来源

码头工人:什么?

我可以尝试解释什么是容器,但是,在Docker网站上找到的解释可能做得更好。 什么是容器? Docker网站上的文章将容器描述为打包代码及其所有依赖项的软件单元。 这样,当从一个环境切换到另一个环境时,应用程序变得更加可靠。 容器是轻巧的,独立的,可执行的软件软件包。

Docker解决的问题是什么?

为什么要使用docker?

容器可以帮助您解决许多问题:

  • 与完全虚拟化不同,您不需要管理程序和来宾操作系统,所有这些开销都被排除在外,并且比虚拟机更轻便。
  • 容器是确定性的,这意味着如果容器在您的计算机中运行,它将在任何地方运行。 人们手动添加或更改对VM的依赖关系并且不通知其他人没有问题。
  • 易于分发,通过注册表,您可以上传容器映像并轻松分发,因此,每次将某些内容合并到分支中时,您都可以使用管道来构建新映像,并且QA中的每个人都可以使用它,或者您可以将所有开发环境都放在一个容器中,因此,当新加入的人可以只获取最新的开发映像并开始工作。
  • 使用编排工具可以很容易地带来PostgreSQL,Redis等外部依赖项。 因此,如果您需要使用docker-compose运行需要空数据库或诸如Wiremock之类的集成或端到端测试,这真的很容易。

这不是什么?

在开始之前,我需要澄清一些事情:

  • Docker容器是Linux容器,这意味着当您在Windows或Mac上运行Docker时,它将在后台启动VM。
  • Docker无法解决您所有的DevOps问题
  • 您仍然需要有关环境的知识才能部署到生产环境
  • 像每个工具一样,它不是万灵丹

为什么一切都澄清了,我们可以开始。

使用容器

Docker基于包含运行该应用程序所需的所有文件的映像创建容器,Docker将运行该应用程序,此后,该容器将被删除,而容器内将不会保存任何内容。

我们可以使用以下命令开始运行第一个容器:

$ docker run hello-world

它会显示的第一件事是您没有图像hello-world因此它将下载它。 但是这个图像从哪里来? Docker有一项名为Docker Hub的服务,用于存储和版本化Docker Hub映像。 它基本上是docker的GitHub。

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
1b930d010525: Pull complete
Digest: sha256:2557e3c07ed1e38f26e389462d03ed943586f744621577a99efb77324b0fe535
Status: Downloaded newer image for hello-world:latest

下载映像后,Docker将创建一个新容器,运行应用程序并在完成所有操作后停止该容器:

Hello from Docker!
This message shows that your installation appears to be working correctly.To generate this message, Docker took the following steps:1. The Docker client contacted the Docker daemon.2. The Docker daemon pulled the "hello-world" image from the Docker Hub.(amd64)3. The Docker daemon created a new container from that image which runs theexecutable that produces the output you are currently reading.4. The Docker daemon streamed that output to the Docker client, which sent itto your terminal.To try something more ambitious, you can run an Ubuntu container with:$ docker run -it ubuntu bashShare images, automate workflows, and more with a free Docker ID:https://hub.docker.com/For more examples and ideas, visit:https://docs.docker.com/get-started/

这是非常基本的事情,我认为我们可以做得更好。 关于运行Web服务器呢? 我们运行docker run -p 8080:80 nginx并等待图像下载。

然后我们可以访问http://localhost:8080 ,我们将看到Nginx的“欢迎”页面。 但是,等等:这一次我们传递了带有一些数字的新标志( -p )。 他们的意思是什么?

港口

处理通过端口工作的容器时,我们必须将本地端口绑定到容器。 与所有Web服务器一样,Nginx始终在端口80上运行。如果要访问该端口,则需要将此端口绑定到localhost。 绑定端口的想法是:

docker run -p <local port>:<container port> <image>

这可能是您将遇到的最常用的命令之一。

管理容器和图像

我们希望能够删除图像,停止正在运行的容器以及删除先前的容器。 为此,我们有一组命令:

  • docker ps :显示正在运行的容器。 添加-a标志以显示已停止的容器。
  • docker rm <contaier id or name> :删除容器。
  • docker images :显示下载的图像。
  • docker rmi <image id> :删除图像。

现在,我们可以对图像进行内务处理了。

码头工人组成

手动运行容器是可行的,但对我们想要的没有帮助。 我们希望能够轻松创建容器,每次都使用相同的配置。

那就是docker-compose进入的地方。 docker-compose是一个编排工具,可以为我们同时管理多个容器。 它基于YAML文件,在该文件中我们指定了所需的容器,并为我们完成了所有工作。

使用docker-compose一个基本用例是在开发环境中帮助管理应用程序的外部依赖关系。 您只需使用数据库,缓存和SMTP服务器设置一个docker-compose文件,任何运行该应用程序的人都可以轻松启动具有这些依赖关系的容器。

现实世界的例子

最好的学习方法是中断生产,现在的想法是在现实生活中使用docker-compose

我们有一个Java应用程序,可以在其中通过RESTful API添加和检索用户。

这些用户存储在PostgreSQL数据库中,但是我们不想安装Postgres。 因此,我们将使用docker-compose为所有克隆该应用程序的人提供Postgres。

docker-compose脚本的剖析

version: '3.1'services:db:image: postgres:10ports:- "5432:5432"environment:POSTGRES_PASSWORD: postgresPOSTGRES_DB: realworld
  • version标签指示可以与脚本一起使用的docker-compose的最低版本
  • services :这是将声明我们的容器的位置。 我们为我们的服务命名,并指定我们想要的服务。 在这种情况下,我们有一个PostgreSQL 10映像。 postgres:10是图像的名称,版本号之间用冒号分隔。
  • ports :我们将容器中的端口5432绑定到本地主机中的5432 ,就像我们之前使用nginx容器所做的那样。
  • environment :设置环境变量(如POSTGRES_PASSWORDPOSTGRES_DB以定义密码并创建一个名为realworld的数据库。 通常,您可以在Docker Hub中的Docker映像的文档中看到可能的变量。

现在,如果我们运行docker-compose up -d-d标志表示已分离,因此该进程将继续在后台运行),我们将能够看到Postgres实例正在运行。

因此,如果我们构建一个jar应用程序,则可以毫无问题地运行该应用程序。

# This will build a jar with all the dependencies
$ ./gradlew shadowJar # You can run the application
$ java -jar build\libs\realworldkata-1.0-SNAPSHOT-all.jar

现在,我们可以访问http://localhost.com:4321/database ,并且应该看到Tables created! 如果一切正常。 我们可以通过访问容器并检查是否在数据库中看到该表来进行双重检查。

首先,我们检查容器的ID:

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
1180df37d9f1        postgres:10         "docker-entrypoint.s…"   About an hour ago   Up About an hour    0.0.0.0:5432->5432/tcp   realworld_db_1

然后,我们访问容器并使用psql应用程序连接到数据库,然后可以列出表。

$ docker exec -it 118 /bin/bash$ root@1180df37d9f1:/# psql -U postgres
psql (10.7 (Debian 10.7-1.pgdg90+1))
Type "help" for help.$ postgres=# \c realworld
You are now connected to database "realworld" as user "postgres".$ realworld=# \dtList of relationsSchema | Name  | Type  |  Owner
--------+-------+-------+----------public | users | table | postgres
(1 row)

建筑图像

现在我们可以使用其他人创建的图像,但是如果我们要使用自己的图像怎么办? 我们可以使用Docker分发我们的应用程序吗? 当然; 这不是业余时间。

您可以通过Dockerfile构建映像,在该Dockerfile中我们将指定依赖项以及如何构建和运行应用程序。

首先,我们通过指定基本映像开始构建Dockerfile 。 该基本映像可以是Ubuntu映像或Java映像。 对于我们的应用程序,我们将使用通过基金会的OpenJ9实现的adoptopenjdk/openjdk11-openj9映像。

FROM adoptopenjdk/openjdk11-openj9

掌握了基本图像之后,我们就可以开始收集源代码来构建应用程序。 为此,我们需要设置WORKDIR并使用COPY命令来获取源文件。

FROM adoptopenjdk/openjdk11-openj9
WORKDIR /realworld
COPY . /realworld

我们有资源; 我们需要立即构建应用程序,因此我们需要RUN命令以生成具有所有依赖项的胖jar。

FROM adoptopenjdk/openjdk11-openj9
WORKDIR /realworld
COPY . /realworld
RUN ./gradlew shadowJar

这是一个Web应用程序,它在TCP端口中接收请求。 为了能够在容器中接收请求,我们EXPOSEEXPOSE的端口。 EXPOSE将说明容器应将哪个端口公开给EXPOSE docker-compose将创建的EXPOSE网络,并作为文档查看运行容器时必须绑定哪个端口。

FROM adoptopenjdk/openjdk11-openj9
WORKDIR /realworld
COPY . /realworld
RUN ./gradlew shadowJar
EXPOSE 4321

最后,我们可以通过传递CMD来运行应用程序

FROM adoptopenjdk/openjdk11-openj9
WORKDIR /realworldCOPY . /realworld
RUN ./gradlew shadowJar
EXPOSE 4321
CMD ["java", "-jar", "build/libs/realworldkata-1.0-SNAPSHOT-all.jar"]

准备好Dockerfile ,我们可以构建映像并从中创建容器。

$ docker build . --tag "realworld"$ docker run realworld
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Exception in thread "main" java.lang.RuntimeExceptionat realworld.infrastructure.ConnectionFactory.build(ConnectionFactory.java:14)at realworld.persistence.daos.UserDAO.<init>(UserDAO.java:18)at realworld.Application.buildUserService(Application.java:41)at realworld.Application.setRoutes(Application.java:28)at realworld.Application.start(Application.java:24)at realworld.Application.main(Application.java:65)

--tag标志用于为图像命名。 您还可以提供诸如devstaging的标签。

该应用程序正在按预期方式运行; 发生错误是因为该容器无权访问另一个运行postgres的容器。 现在我们知道一切正常,我们可以开始改进容器构建的某些部分。

.dockerignore

与具有.gitignore git一样, .dockerignore具有.dockerignore ,这是一个从容器副本中排除文件的文件。 让我们创建一个不复制特定于IDE的文件夹和输出文件夹,这样我们可以更快地构建。

.gradle/
.idea/
build/
out/

多阶段构建

我们正在使用所有源代码创建docker映像,并且由于我们只想运行我们的应用程序,因此无需在最终的jar中分发它们。 该应用程序的源代码位于容器内,任何有权访问该图像的人都可以看到它,这也将使我们的图像变大而无需任何需要。 为了解决这个问题,我们将进行multi-stage构建。

什么是

多阶段构建是一种以不同的步骤在多个容器之间拆分构建映像的过程的方式,有点像CI构建。 要将常规构建转换为multi-stage构建很容易,只需在Dockerfile添加另一个FROM

在我们的案例中,我们希望拆分用于构建应用程序的环境和将运行的轻量级环境。

首先,我们要处理我们已经拥有的容器。 我们需要做一些事情:

  • 为构建阶段命名我们可以通过在基础映像前面添加as <name>来实现。
  • 然后,我们必须删除将要运行应用程序的内容。为此,我们从文件中删除了EXPOSECMD ,但不删除,我们将在以后使用它。

现在,我们可以开始创建将运行该应用程序的映像:

  • 定义图像。 我们不需要Gradle或Maven的完整图像。 实际上,我们甚至不需要JDK,我们只需要JRE,因此我们可以使用仅具有Java运行时的adoptopenjdk/openjdk11:jre-11.0.2.9-alpine映像。 它基于名为Alpine的轻量级Linux发行版。
  • 我们可以与上一个阶段有相同的WORKDIR
  • 现在,我们将COPY要构建的jar。在这种情况下,我们将在上一个阶段使用--from=build从要复制的文件之前的容器中复制jar。
  • 现在我们只需要放入之前保存的EXPOSECMD

现在,当我们构建容器时,泊坞窗将启动一个容器来构建应用程序并使用这些文件创建另一个映像,它们会删除之前步骤中的任何内容,因此无需编写清理脚本。

FROM adoptopenjdk/openjdk11-openj9 as build
WORKDIR /realworld
COPY . /realworld
RUN ./gradlew shadowJarFROM adoptopenjdk/openjdk11:jre-11.0.2.9-alpine
WORKDIR /realworld
COPY --from=build /realworld/build/libs/realworldkata-1.0-SNAPSHOT-all.jar .
EXPOSE 4321
CMD ["java", "-jar", "realworldkata-1.0-SNAPSHOT-all.jar"]

将图像添加到docker-compose.yml

现在我们已经正确构建了映像,可以将其添加到docker-compose.yml ,但是与我们已经拥有的postgres映像不同,我们希望基于Dockerfile来构建映像,并且还需要设置一些环境变量来连接到数据库。

因此,我们将新服务添加到文件中。 而不是使用image ,我们将使用build并将相对路径传递到我们要构建的Dockerfile

我们映射端口,并为DB_HOST添加指向我们的db服务和postgres端口的环境变量。 最后,我们添加depends_on表示我们依赖于db服务。

version: '3.1'services:db:image: postgres:10ports:- "5432:5432"environment:POSTGRES_PASSWORD: postgresPOSTGRES_DB: realworldrealworld:build: .ports:- "4321:4321"environment:DB_HOST: "db"depends_on:- db

当我们尝试实例化容器时,它还无法正常工作:为什么? 我还不知道,让我们检查一下日志。

这是我们日志的重要部分: depends_on等待容器准备就绪,但不等待初始化后运行的东西。

db_1         | fixing permissions on existing directory /var/lib/postgresql/data ... ok
db_1         | creating subdirectories ... ok
db_1         | selecting default max_connections ... 100
db_1         | selecting default shared_buffers ... 128MB
db_1         | selecting dynamic shared memory implementation ... posix
realworld_1  | Picked up JAVA_TOOL_OPTIONS:
db_1         | creating configuration files ... ok
db_1         | running bootstrap script ... ok
realworld_1  | SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
realworld_1  | SLF4J: Defaulting to no-operation (NOP) logger implementation
realworld_1  | SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
db_1         | performing post-bootstrap initialization ... ok
db_1         | syncing data to disk ... ok

基本故障排除

在这种情况下,我们有一个“理论”,即应用程序在一切准备就绪之前试图连接到数据库。 我们必须测试,如果在数据库准备就绪后运行应用程序,则一切都会正常。

我们可以验证的最基本的操作是生成容器并手动启动应用程序,但是如何使用docker-compose连接到容器?

就像在Docker中运行单个容器一样, docker-compose提供了run方法,我们可以使用该方法访问容器内的shell。

# docker-compose run <service> <command>
docker-compose run realworld /bin/sh

这将使应用程序可以访问容器,从而使我们能够运行:

$ java -jar realworldkata-1.0-SNAPSHOT-all.jar
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

如果应用程序未引发与数据库有关的任何错误,则说明该应用程序正在运行,我们可以继续创建问题的解决方案。

破解我们的方式

如何解决这个问题? 添加一个脚本来检查数据库是否已启动,并且仅在应用程序准备就绪时才运行它,即可完成工作。

现代问题,需要现代解决方案。

#! /bin/sh# Set to exit on errorset -e# We need to install the psql application to connect to the dbapk add --no-cache postgresql-client# Keep in a loop until connects to the postgres databaseuntil PGPASSWORD="postgres" psql -h "${DB_HOST}" -U "postgres" -c '\q'; do>&2 echo "Postgres is unavailable - sleeping"sleep 1done>&2 echo "Postgres is up - executing command"# Exec the command with the arguments that were passedexec $@

我们已经准备好映像,因此可以使用脚本进行重建并更改run命令,但是随后我们将在使用映像的所有位置进行此检查,我们不希望这样做,因为在其他地方,我们可能会使用不在Docker容器中的数据库。

因此,我们可以从映像中覆盖命令并运行脚本。

我们要做的第一件事是将脚本放入容器中,我们已经构建了映像,因此我们无法再次使用COPY ,在这种情况下,我们可以在容器内创建一个卷。

卷数

卷是将文件夹从主机安装到容器中的一种方法。 该文件夹内的所有内容都将镜像到容器。 当您想要保存日志之类的内容或将其保存在容器中运行的数据库中时,这很好。

我们更改docker-compose.yml以添加我们的新功能:

version: '3.1'services:db:image: postgres:10ports:- "5432:5432"environment:POSTGRES_PASSWORD: postgresPOSTGRES_DB: realworldrealworld:build: .ports:- "4321:4321"environment:DB_HOST: "db"depends_on:- dbvolumes:- "./scripts:/scripts"command: ["/scripts/wait-for-db.sh", "java", "-jar", "realworldkata-1.0-SNAPSHOT-all.jar"]

我们添加了volumes标记,将我们的应用程序文件夹内的scripts文件夹链接到容器根目录中的scripts文件夹,并且我们有一个要与该脚本一起运行的新命令以及该应用程序的运行命令。

ARG使我们的形象更加灵活

现在,该应用程序正在暴露端口“ 4321”,这非常不灵活。 如果需要任何更改,唯一的方法是在docker-compose文件中进行映射以映射到其他端口。 使用Dockerfile ARG可以使此操作更加灵活。

为此需要进行哪些更改?

Dockerfile设置ARG关键字。 这将接收参数名称和默认值。 如果不想每次都在构建过程中传递该值,最好设置一个默认值。

# ARG NAME=<value>
ARG PORT=4321

使用ARG时要注意的另一件事是示波器。 您不能使用在FROM后面声明的ARG 。 在代码中像变量一样思考:您不能在声明变量之前使用变量,也不能使用在另一个函数内部声明的变量。

创建了ARG ,就该设置环境变量PORT了,以便应用程序知道要使用哪个端口。 可以使用ENV关键字来完成。

# ENV NAME $arg
ENV PORT $PORT

最后,我们必须更改EXPOSE关键字以使用ARG而不是硬编码值。

EXPOSE $PORT

最终结果将是:

FROM adoptopenjdk/openjdk11:jdk-11.0.2.9 as build
WORKDIR /realworld
COPY . /realworld
RUN ./gradlew shadowJarFROM adoptopenjdk/openjdk11:jre-11.0.2.9-alpine
ARG PORT=4321
WORKDIR /realworld
COPY --from=build /realworld/build/libs/realworldkata-1.0-SNAPSHOT-all.jar .
ENV PORT $PORT
EXPOSE $PORT
CMD ["java", "-jar", "realworldkata-1.0-SNAPSHOT-all.jar"]

并构建传递参数的容器:

# docker build . --build-arg ARG=<value>
$ docker build . -t realworld:ports --build-arg PORT=4332

要检查容器是否以正确的端口运行,您可以使用docker ps查看暴露的端口

$ docker run -it realworld:args /bin/sh$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
10b6105d1db2        realworld:args      "/bin/sh"           5 seconds ago       Up 4 seconds        4332/tcp            gravel_pit

您可以在PORTS列中看到它正在暴露4332/tcp ,就像在args中传递了一样,但是如果要使用docker-compose这样做,该怎么办? 有什么办法可以通过yml文件传递build-arg吗? 当然。

更改docker-compose.yaml以使用args标签在构建部件中传递参数。 现在,该build将具有多个值。 必须添加关键context来设置Dockerfile的位置。

# ...realworld:build: context: .args:PORT: 4332ports:- "4332:4332"environment:DB_HOST: "db"depends_on:- dbvolumes:- "./scripts:/scripts"command: ["/scripts/wait-for-db.sh", "java", "-jar", "realworldkata-1.0-SNAPSHOT-all.jar"]

进行所有更改后,只需运行docker-compose up ,就可以通过尝试创建表来检查一切是否在正确的端口中运行

$ curl localhost:4332/database
Tables created!

入口点

CMD不是在Docker中启动容器的唯一方法,实际上,在执行CMD之前,容器具有ENTRYPOINT 。 有时,您希望容器在启动应用程序之前进行更复杂的启动并执行一些命令或脚本。 Docker将ENTRYPOINT与传递给容器的CMD结合在一起,因此,在docker-compose.yml ,我们可以从java命令中拆分刚刚构建wait-for-db.sh的命令。

因此,如果Dockerfile看起来像这样:

FROM adoptopenjdk/openjdk11:jdk-11.0.2.9 as build
WORKDIR /realworld
COPY . /realworld
RUN ./gradlew shadowJarFROM adoptopenjdk/openjdk11:jre-11.0.2.9-alpine
ARG PORT=4321
WORKDIR /realworld
COPY --from=build /realworld/build/libs/realworldkata-1.0-SNAPSHOT-all.jar .
ENV PORT $PORT
EXPOSE $PORT
ENTRYPOINT ["wait-for-db.sh"]
CMD ["java", "-jar", "realworldkata-1.0-SNAPSHOT-all.jar"]

这将像wait-for-db.sh java -jar realworldkata-1.0-SNAPSHOT-all.jar 。 该脚本可以做很多事情,最后执行应用程序。

Postgres做这样的事情。 它没有以postgres命令作为启动点,而是执行了一个脚本,该脚本设置将存储数据的文件夹,在正确的环境变量中设置密码,并检查是否有任何.sql.sh文件要运行。启动数据库。

docker-library / postgres

不要使用ENTRYPOINT启动您的应用程序。 使用CMD因此您可以使用docker run覆盖命令。

Docker集线器和容器注册表

在每台机器上构建相同的docker镜像并不是最直观的事情。 您可能想在没有所有源代码的情况下仅在docker-compose.yml情况下在另一台机器上使用该映像。

首先是在Docker Hub上注册一个帐户,然后在命令行中使用该帐户登录:

$ docker login

登录后,您可以将图像推送到存储库。 存储库基于您在构建映像时提供的标签名称。 构建第一个图像时,有--tag标志为图像命名; Docker Hub中的存储库将使用相同的名称。 通过在版本库中添加一个版本,可以在同一映像中拥有多个版本。

# docker build . --tag <repository>/<image-name>:<version>
$ docker build . --tag "andretorrescodurance/realworld:0.1"

因此,我们现在可以构建图像,设置完所有内容后,您可以使用

# docker push <repository>:<version>
$ docker push andretorrescodurance/realworld:0.1

如果未在映像名称之前添加存储库,则可能难以将映像推送到Docker Hub。

现在,您可以从Docker docker-compose.yml Docker Hub中使用映像,而无需从头开始构建,而无需将源文件发送到任何地方。

version: '3.1'services:db:image: postgres:10ports:- "5432:5432"environment:POSTGRES_PASSWORD: postgresPOSTGRES_DB: realworldrealworld:image: andretorrescodurance/realworld:0.1ports:- "4321:4321"environment:DB_HOST: "db"depends_on:- dbvolumes:- "./scripts:/scripts"command: ["/scripts/wait-for-db.sh", "java", "-jar", "realworldkata-1.0-SNAPSHOT-all.jar"]

完成更改并使用容器后,我们可以结束此帖子。

资料来源:

  • https://docs.docker.com/engine/reference/builder/
  • https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
  • https://docs.docker.com/compose/compose-file/

翻译自: https://www.javacodegeeks.com/2019/04/containers-docker.html

带有Docker的容器相关推荐

  1. docker server 容器连接sql_Docker使用指南

    一.Docker安装 在Ubuntu系统下安装: apt-get install docker 在Fedora/CentOS系统下安装: yum install docker dnf install ...

  2. docker 查看容器_Docker介绍

    docker介绍 什么是docker?我们先看一下官方文档对docker的定义.翻译一下就是:Docker是一个集开发,发布和运行应用程序的开放平台.Docker能够分离应用和基础架构,从而可以使得用 ...

  3. docker停止容器后配置_Docker 自学笔记 - april_aaa

    Docker为什么会出现? 一款产品从开发到上线,从操作系统,到运行环境,再到应用部署.作为开发+运维之间的协作我们需要关心很多东西,这也是很多互联网公司都不得不面对的问题,特别是各个版本的迭代之后, ...

  4. Docker(容器) 部署安装

    一.Docker 部署安装 1.Docker 的概念 Docker 是一个开源的应用容器引擎,让开发这可以打包他们的应用以及依赖包到一个可以移植的境相当中,然后发布到任何流行 的Linux或者Wind ...

  5. Docker常用容器命令

    常用容器命令 有镜像才能创建容器,这是根本前提(下载一个CentOS镜像演示) docker pull centos 新建并启动容器 格式: docker run [OPTIONS] IMAGE [C ...

  6. docker镜像容器的创建删除

    目录 1. Docker是什么? 2. CentOS7用阿里云Docker Yum源在线安装Docker 3. 镜像 3.1 配置加速器 3.2 搜索镜像 3.3 下载镜像 3.4 查看宿主机上的镜像 ...

  7. 【docker创建容器的坑】WSL启动nvidia-docker镜像:报错libnvidia-ml.so.1- file exists- unknown

    可能得错误一: 今天使用docker创建容器的时候总是出错,最后锁定问题在"--gpus all"这里: 不加--gpu all可以运行,加入了--gpus all就出错: doc ...

  8. docker 镜像容器导入导出、查看日志、拷贝文件命令

    1. 本地文件拷贝到docker 容器中,参考 docker cp /root/pcl-pcl-1.8.1.tar.gz 7ff95b333e12:/docker cp /root/lib64_a 7 ...

  9. Docker将容器制作成镜像并提交到远程仓库

    Docker将容器制作成镜像并提交到远程仓库 步骤如下 先在dockerhub上创建一个自己的用户https://hub.docker.com/.或者在阿里云也可以. 2. 然后先创建一个空的镜像名. ...

最新文章

  1. [deviceone开发]-组件功能演示示例
  2. 如何在Python中匹配最接近的字符串
  3. awstats linux日志分析,Linux环境下安装部署AWStats日志分析系统实例
  4. Java之new一个对象简单过程
  5. docker 容器启动顺序_Docker容器启动时初始化Mysql数据库
  6. httpd svn 编译安装_linux下php7安装与Apache配置
  7. 斯大林格勒拖拉机厂LCA项目研制成功
  8. Django 模板标签 换行导致异常的处理 linebreaksbr
  9. idea给main方法附带参数
  10. expdp的常用用法
  11. 大话存储系列21——存储系统内部IO 上
  12. valgrind检测内存泄露
  13. 关于AD9371FilterWizard无法运行问题
  14. uCOSIII 实时操作系统(一) - 简介
  15. 数据库面试题:Redis如何保证数据一致性
  16. jqgrid实现表头合并功能
  17. IP和MAC地址的区别与联系
  18. PyTorch中的topk函数详解
  19. 矩阵特征值和特征向量求解——特征值分解
  20. activiti 多实例任务

热门文章

  1. Linux下安装Dynamixel Wizard 2.0
  2. OSChina 周五乱弹 —— 前老板借前前员工钱给现员工发工资
  3. 【java】生成【PDF】后端接口-- java生成PDF的第二步
  4. 递归、字符串操作的方法、实现继承的方法有哪些、for in循环、移动web和响应式区别 (Date 2023/1/2)
  5. Stateless,stateful实现
  6. firfox新标签页打开的设置与优化
  7. FITC-Phalloidin|异硫氰酸荧光素标记鬼笔环肽|标记物
  8. python codecs_Python codecs.register方法代码示例
  9. 科技化浪潮下,金融牌照还有没有价值?
  10. android 课程格子,课程表也能撩学妹?安卓课程格子App体验