公司要新招美女跟我学docker,你来吗?(2)

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 公司要新招美女跟我学docker,你来吗?(2)

5. OnBuild优化Dockerfile

虽然Dockerfile是按从上到下的顺序执行的,但当该映像用作另一个映像的基础时,您可以触发一条指令在稍后的时间执行。


ONBUILD指令可以为镜像添加触发器。


当我们在一个Dockerfile文件中加上ONBUILD指令,该指令对利用该Dockerfile构建镜像(比如为A镜像)不会产生实质性影响。


但是当我们编写一个新的Dockerfile文件来基于A镜像构建一个镜像(比如为B镜像)时,这时构造A镜像的Dockerfile文件中的ONBUILD指令就生效了,在构建B镜像的过程中,首先会执行ONBUILD指令指定的指令,然后才会执行其它指令。


需要注意的是,如果是再利用B镜像构造新的镜像时,那个ONBUILD指令就无效了,也就是说只能再构建子镜像中执行,对孙子镜像构建无效。其实想想是合理的,因为在构建子镜像中已经执行了,如果孙子镜像构建还要执行,相当于重复执行,这就有问题了。


利用ONBUILD指令,实际上就是相当于创建一个模板镜像,后续可以根据该模板镜像创建特定的子镜像,需要在子镜像构建过程中执行的一些通用操作就可以在模板镜像对应的dockerfile文件中用ONBUILD指令指定。 从而减少dockerfile文件的重复内容编写。


下面是Node.js的OnBuild Dockerfile。与前面的场景不同,应用程序指定命令以ONBUILD作为前缀。

Dockerfile1:

FROM node:7
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
ONBUILD COPY package.json /usr/src/app/
ONBUILD RUN npm install
ONBUILD COPY . /usr/src/app
CMD [ "npm", "start" ]

结果是,我们可以构建这个映像,但在将构建的映像用作基本映像之前,不会执行应用程序特定的命令。然后,它们将作为基本映像构建的一部分执行。


有了复制代码、安装依赖项和启动应用程序的所有逻辑后,在应用程序级别上需要定义的唯一方面就是要公开哪个端口。


创建OnBuild映像的好处是,我们的Dockerfile现在更简单,可以轻松地跨多个项目重用,而不必重新运行相同的步骤,以提高构建时间。

dockerfile2:

FROM node:7-onbuild
EXPOSE 3000

已经为您创建了上一步中的Dockerfile。基于OnBuild docker文件构建映像与之前相同。OnBuild命令将像在基础Dockerfile中一样执行。

总之,唯有 ONBUILD 是为了帮助别人定制自己而准备的。而不是为了构建当前镜像的。

docker build -t my-nodejs-app -f dockerfile2
docker run -d --name my-running-app -p 3000:3000 my-nodejs-app
curl http://ip:3000

6. 忽略文件.dockerignore

6.1 Docker Ignore

为了防止敏感文件或目录被错误地包含在映像中,您可以添加一个名为.dockerignore的文件。

Dockerfile将工作目录复制到Docker映像中。因此,这将包括潜在的敏感信息,如我们希望在映像外部管理的密码文件。

$ ls
Dockerfile  cmd.sh  passwords.txt
$ cat Dockerfile 
FROM alpine
ADD . /app
COPY cmd.sh /cmd.sh
CMD ["sh", "-c", "/cmd.sh"]
$ cat cmd.sh 
echo "Hello World"
$ cat passwords.txt
admin:admin
$ docker build -t password .
Sending build context to Docker daemon  4.096kB
Step 1/4 : FROM alpine
 ---> 3fd9065eaf02
Step 2/4 : ADD . /app
 ---> 8e7bc5dac978
Step 3/4 : COPY cmd.sh /cmd.sh
 ---> ec486638d561
Step 4/4 : CMD ["sh", "-c", "/cmd.sh"]
 ---> Running in fe4cba7a87b2
Removing intermediate container fe4cba7a87b2
 ---> 4c270e87d27c
Successfully built 4c270e87d27c
Successfully tagged password:latest
$ docker run password ls /app
Dockerfile
cmd.sh
passwords.txt

这将包括密码文件。

下面的命令将在.dockerignore文件中包含password .txt,并确保它不会意外地出现在容器中。dockerignore文件将存储在源代码管理中,并与团队共享,以确保每个人都是一致的。

echo passwords.txt >> .dockerignore

.dockerignore文件支持目录和正则表达式来定义限制,非常类似于.gitignore。这个文件还可以用来提高构建时间,我们将在下一步研究这个问题。

构建映像,因为Docker Ignore文件不应该包括密码文件。

$ docker build -t nopassword .
Sending build context to Docker daemon  4.096kB
Step 1/4 : FROM alpine
 ---> 3fd9065eaf02
Step 2/4 : ADD . /app
 ---> 36ee8b3bc4ee
Step 3/4 : COPY cmd.sh /cmd.sh
 ---> a4c8fc953352
Step 4/4 : CMD ["sh", "-c", "/cmd.sh"]
 ---> Running in 5b7774763eca
Removing intermediate container 5b7774763eca
 ---> b6b6eac92cce
Successfully built b6b6eac92cce
Successfully tagged nopassword:latest
$ docker run nopassword ls /app
Dockerfile
cmd.sh

如果您需要使用密码作为RUN命令的一部分,那么您需要复制、执行和删除文件作为单个RUN命令的一部分。只有Docker容器的最终状态被持久化到映像中。

6.2 Docker 构建安全上下文

dockerignore文件可以确保Docker映像中不包含敏感细节。但是,它们也可以用来提高映像的构建时间。


在环境中,已经创建了100M的临时文件。Dockerfile永远不会使用这个文件。当您执行构建命令时,Docker将整个路径内容发送给引擎,以便它计算要包含哪些文件。因此,发送100M文件是不需要的,并创建了一个较慢的构建。


您可以通过执行该命令看到100M的影响。

$ docker build -t large-file-context .
Sending build context to Docker daemon  104.9MB
Step 1/4 : FROM alpine
 ---> 3fd9065eaf02
Step 2/4 : ADD . /app
 ---> cb1e74c524af
Step 3/4 : COPY cmd.sh /cmd.sh
 ---> e3dbbbd57ddf
Step 4/4 : CMD ["sh", "-c", "/cmd.sh"]
 ---> Running in 5fcb5e771266
Removing intermediate container 5fcb5e771266
 ---> 7e398a079fb0
Successfully built 7e398a079fb0
Successfully tagged large-file-context:latest

在下一步中,我们将演示如何提高构建的性能。

明智的做法是忽略.git目录以及在映像中下载/构建的依赖项,比如node_modules。在Docker容器中运行的应用程序永远不会使用它们,只会增加构建过程的开销。

6.3 优化构建

以同样的方式,我们使用.dockerignore文件来排除敏感文件,我们可以使用它来排除我们不想在构建期间发送到Docker构建上下文的文件。

要加快构建速度,只需在忽略文件中包含大文件的文件名。

echo big-temp-file.img >> .dockerignore

当我们重建图像时,它将会快得多,因为它不需要复制100M文件。

$ docker build -t no-large-file-context .
Sending build context to Docker daemon  4.096kB
Step 1/4 : FROM alpine
 ---> 3fd9065eaf02
Step 2/4 : ADD . /app
 ---> Using cache
 ---> 4a1be3423c29
Step 3/4 : COPY cmd.sh /cmd.sh
 ---> Using cache
 ---> e30db2162cca
Step 4/4 : CMD ["sh", "-c", "/cmd.sh"]
 ---> Using cache
 ---> 4d4964ddbb00
Successfully built 4d4964ddbb00
Successfully tagged no-large-file-context:latest

当忽略.git这样的大目录时,这种优化会产生更大的影响。

7. 容器持久化数据

数据容器是唯一负责存储/管理数据的容器。

与其他容器一样,它们由主机系统管理。然而,当您执行docker ps命令时,它们不会运行。

要创建数据容器,我们首先要创建一个具有知名名称的容器以供将来参考。我们使用busybox作为基础,因为它体积小,重量轻,以防我们想要探索和移动容器到另一个主机。

在创建容器时,我们还提供了一个-v选项来定义其他容器读取/保存数据的位置。

$ docker create -v /config --name dataContainer busybox

容器就绪后,我们现在可以将文件从本地客户端目录复制到容器中。

下面的命令将config.conf文件复制到dataContainer和config.conf目录中。

$ docker cp config.conf dataContainer:/config/

现在我们的Data Container有了配置,我们可以在启动需要配置文件的依赖容器时引用该容器。


使用——volumes-from <container>选项,我们可以使用正在启动的容器中来自其他容器的挂载卷。在这种情况下,我们将启动一个Ubuntu容器,它引用了我们的数据容器。当我们列出config目录时,它将显示来自附加容器的文件。

$ docker run --volumes-from dataContainer ubuntu ls /config
config.conf

如果/config目录已经存在,那么volumes-from将被覆盖并成为所使用的目录。可以将多个卷映射到一个容器。

如果我们想将Data Container移动到另一台机器,那么我们可以将其导出到.tar文件。

$ docker export dataContainer > dataContainer.tar

命令docker import dataContainer.tar会将数据容器导入到docker中。

8. 容器之间的交流

连接到容器最常见的场景是应用程序连接到数据存储。创建链接时的关键方面是容器的名称。所有容器都有名称,但为了在处理链接时更容易一些,为所连接的源容器定义一个友好的名称是很重要的。

运行一个友好的名称为redis-server的redis服务器,我们将在下一步连接它。这将是源容器。

$ docker run -d --name redis-server redis

Redis是一个快速的、开源的键值数据存储。

要连接到源容器,在启动新容器时使用--link <container-name|id>:<alias>选项。容器名引用上一步中定义的源容器,而别名定义主机的友好名称。


通过设置别名,我们可以将应用程序的配置方式与基础设施的调用方式分开。这意味着应用程序配置在连接到其他环境时不需要更改。


在这个例子中,我们打开一个链接到redis-server的Alpine容器。我们已经将别名定义为redis。当一个链接被创建时,Docker将做两件事。


首先,Docker将基于链接到容器的环境变量设置一些环境变量。这些环境变量为您提供了一种通过已知名称引用端口和IP地址等信息的方法。


可以使用env命令输出所有环境变量。例如:

$ docker run --link redis-server:redis alpine env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=bae49bf11c01
REDIS_PORT=tcp://172.18.0.2:6379
REDIS_PORT_6379_TCP=tcp://172.18.0.2:6379
REDIS_PORT_6379_TCP_ADDR=172.18.0.2
REDIS_PORT_6379_TCP_PORT=6379
REDIS_PORT_6379_TCP_PROTO=tcp
REDIS_NAME=/angry_franklin/redis
REDIS_ENV_GOSU_VERSION=1.12
REDIS_ENV_REDIS_VERSION=6.2.5
REDIS_ENV_REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-6.2.5.tar.gz
REDIS_ENV_REDIS_DOWNLOAD_SHA=4b9a75709a1b74b3785e20a6c158cab94cf52298aa381eea947a678a60d551ae
HOME=/root

通过创建链接,您可以以与在您的网络中运行的服务器相同的方式ping源容器。

$ docker run --link redis-server:redis alpine ping -c 1 redis
PING redis (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.202 ms
--- redis ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.202/0.202/0.202 ms

通过创建链接,应用程序可以以通常的方式与源容器进行连接和通信,而无需考虑两个服务都运行在容器中这一事实。

这是一个简单的node.js应用程序,它使用主机名redis连接到redis。

$ docker run -d -p 3000:3000 --link redis-server:redis katacoda/redis-node-docker-example

发送一个HTTP请求到应用程序将存储请求在Redis和返回一个计数。如果发出多个请求,就会看到计数器的递增,因为条目被持久化了。

$ curl ip:3000
This page was generated after talking to redis.
Application Build: 1
Total requests: 1
IP count: 
    ::ffff:172.17.0.33: 1
$ curl ip:3000
This page was generated after talking to redis.
Application Build: 1
Total requests: 2
IP count: 
    ::ffff:172.17.0.33: 2

以同样的方式,您可以将源容器连接到应用程序,也可以将它们连接到自己的CLI工具。

下面的命令将启动一个redis -cli工具的实例,并通过它的别名连接到redis服务器。

$ docker run -it --link redis-server:redis redis redis-cli -h redis
redis:6379> info

KEYS *命令将输出当前存储在源redis容器中的内容。

9. Docker 网络

9.1 创建网络

第一步是使用CLI创建网络。这个网络将允许我们附加多个容器,这些容器将能够发现彼此。在本例中,我们将从创建一个后端网络开始。所有连接到我们后端的容器都将在这个网络上。

$ docker network create backend-network
89109e8de51aee15171ac6ec7257af040aecc66906777acfbbe88a715dcdb9d4

当我们启动新的容器时,我们可以使用--net属性来分配它们应该连接到哪个网络。

$ docker run -d --name=redis --net=backend-network redis

9.2 连接网络

与使用链接不同,docker网络的行为类似于传统网络,节点可以附加/分离。

首先你会注意到Docker不再分配环境变量或更新容器的hosts文件。使用下面的两个命令,您会注意到它不再提到其他容器。

$ docker run --net=backend-network alpine env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=d566ff9c9a14
HOME=/root
$ docker run --net=backend-network alpine cat /etc/hosts
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.19.0.3      97c3a236a7e6

相反,容器可以通过Docker中的嵌入式DNS服务器进行通信。这个DNS服务器通过IP 127.0.0.11分配给所有容器,并在resolv.conf文件中设置。

$ docker run --net=backend-network alpine cat /etc/resolv.conf
nameserver 127.0.0.11
options ndots:0

当容器试图通过众所周知的名称(如Redis)访问其他容器时,DNS服务器将返回正确的容器的IP地址。在这种情况下,Redis的完全限定名将是Redis .backend-network

$ docker run --net=backend-network alpine ping -c1 redis
PING redis (172.19.0.2): 56 data bytes
64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.324 ms
--- redis ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.324/0.324/0.324 ms

9.3 连接两个容器

Docker支持多个网络和容器同时连接到多个网络。

例如,让我们用Node.js应用程序创建一个单独的网络,它与我们现有的Redis实例通信。

第一个任务是以同样的方式创建一个新的网络。

$ docker network create frontend-network
37e9702dd8f695f515b988beddd1cf4d4f7b38447a4e4177d98fcf96231321b2

当使用connect命令时,可以将现有容器附加到网络上。

$ docker network connect frontend-network redis


当我们启动web服务器时,考虑到它连接到同一个网络,它将能够与我们的Redis实例通信。

$ docker run -d -p 3000:3000 --net=frontend-network katacoda/redis-node-docker-example
$ curl ping:3000
This page was generated after talking to redis.
Application Build: 1
Total requests: 1
IP count: 
    ::ffff:172.17.0.51: 1
$ curl ping:3000
This page was generated after talking to redis.
Application Build: 1
Total requests: 2
IP count: 
    ::ffff:172.17.0.51: 2

9.4 创建别名

使用docker网络时仍然支持链接,并提供了一种方法来定义容器名的别名。这将为容器提供一个额外的DNS条目名称和被发现的方式。当使用--link时,嵌入式DNS将保证本地化查找结果只在使用--link的容器上。


另一种方法是在将容器连接到网络时提供别名。

下面的命令将用db的别名将我们的Redis实例连接到前端网络。

docker network create frontend-network2
docker network connect --alias db frontend-network2 redis

当容器试图通过名称db访问服务时,他们将得到我们的Redis容器的IP地址。

$ docker run --net=frontend-network2 alpine ping -c1 db
PING db (172.21.0.2): 56 data bytes
64 bytes from 172.21.0.2: seq=0 ttl=64 time=0.170 ms
--- db ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.170/0.170/0.170 ms

9.5 断开容器连接

创建好网络后,我们可以使用CLI来探索细节。下面的命令将列出我们主机上的所有网络。

$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
89109e8de51a        backend-network     bridge              local
6fe697227a58        bridge              bridge              local
37e9702dd8f6        frontend-network    bridge              local
b0a9dbbb0bab        frontend-network2   bridge              local
fa054a9af353        host                host                local
f50397115ef2        none                null                local

然后,我们可以探索网络,查看连接的容器及其IP地址。

$ docker network inspect frontend-network
[
    {
        "Name": "frontend-network",
        "Id": "37e9702dd8f695f515b988beddd1cf4d4f7b38447a4e4177d98fcf96231321b2",
        "Created": "2021-09-28T12:52:03.799072129Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.20.0.0/16",
                    "Gateway": "172.20.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "80bb046b3ac46cd0efa7b66640e0eaf297f65d39ad080193758f6d19d10c6d3e": {
                "Name": "redis",
                "EndpointID": "a8fb389c6672f0ab173c39b273064922ea252d3fce5094d1864fb2b36cdfa25d",
                "MacAddress": "02:42:ac:14:00:02",
                "IPv4Address": "172.20.0.2/16",
                "IPv6Address": ""
            },
            "b28cbfb9b69e68d070f8fef5ddd2bbabb6e410ebeb0905b917dfd8eb103d85a3": {
                "Name": "inspiring_archimedes",
                "EndpointID": "80afb91170ab08def612373bf78be60609dbb173bb3d57b3abda7b578ff001cc",
                "MacAddress": "02:42:ac:14:00:03",
                "IPv4Address": "172.20.0.3/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

下面的命令断开redis容器与前端网络的连接。

$ docker network disconnect frontend-network redis

10. 使用卷持久化存储

10.1 --volumes,-v

在启动容器时创建和分配Docker卷。数据卷允许将主机目录映射到容器,以便共享数据。


这种映射是双向的。它允许从容器内部访问存储在主机上的数据。这还意味着进程在容器内保存的数据会持久化到主机上。


这个例子将使用Redis作为一种持久化数据的方法。在下面启动一个Redis容器,并使用-v参数创建一个数据卷。它指定容器中保存到/data目录中的任何数据都应该持久化到主机的/docker/redis-data目录中。

 docker run  -v /docker/redis-data:/data  --name r1 -d redis redis-server --appendonly yes

我们可以使用下面的命令将数据输送到Redis实例中。

$ cat data | docker exec -i r1 redis-cli --pipe
All data transferred. Waiting for the last reply...
Last reply received from server.
errors: 0, replies: 1

Redis会将这些数据保存到磁盘。在主机上,我们可以调查应该包含Redis数据文件的映射直接。

$ ls /docker/redis-data
appendonly.aof

这个目录可以挂载到第二个容器。一种用法是让Docker容器对数据执行备份操作。

$  docker run  -v /docker/redis-data:/backup ubuntu ls /backup
appendonly.aof

10.2 --volumes-from

数据卷映射给主机有利于数据持久化。然而,要从另一个容器访问它们,您需要知道容易出错的确切路径。


另一种方法是使用-volumes-from。该参数将映射卷从源容器映射到正在启动的容器。


在这个例子中,我们将Redis容器的卷映射到Ubuntu容器。/data目录只存在于我们的Redis容器中,然而,因为-volumes-from,Ubuntu容器可以访问数据。

$  docker run --volumes-from r1 -it ubuntu ls /data
appendonly.aof

这允许我们访问来自其他容器的卷,而不必关心它们是如何在主机上持久化的。

10.3 只读卷

挂载卷使容器对目录具有完全的读和写访问权限。通过对挂载目录添加“ro”权限,可以对该目录设置只读权限。如果容器试图修改目录中的数据,则会出错。

$ docker run -v /docker/redis-data:/data:ro -it ubuntu rm -rf /data
rm: cannot remove '/data/appendonly.aof': Read-only file system

11. 管理日志

当你启动一个容器时,Docker将跟踪进程的Standard OutStandard Error输出,并通过客户端使它们可用。

在后台,有一个名为Redis -server的Redis实例运行。通过使用Docker客户端,我们可以访问标准输出和标准错误输出

$ docker logs redis-server

默认情况下,Docker日志使用JSON -file记录器输出,这意味着输出存储在主机上的JSON文件中。这可能会导致大文件填满磁盘。因此,您可以更改日志驱动程序以移动到不同的目的地。


Syslog日志驱动程序将所有容器日志写到主机的中央Syslog日志中。syslog是一种广泛使用的消息记录标准。它允许生成消息的软件、存储消息的系统以及报告和分析消息的软件分离。


此日志驱动程序设计用于外部系统收集和聚合syslog日志。下面的命令将redis日志重定向到syslog

$ docker run -d --name redis-syslog --log-driver=syslog redis

如果你试图使用客户端查看日志,你会收到错误FATA[0000] "logs"命令只支持"json-file"日志驱动程序。


相反,您需要通过syslog流访问它们。


第三个选项是禁用容器上的日志记录。这对于在日志记录中非常冗长的容器特别有用。


当容器启动时,只需将log-driver设置为none。不会记录任何输出。

docker run -d --name redis-none --log-driver=none redis

inspect命令允许您识别特定容器的日志记录配置。下面的命令将为每个容器输出LogConfig部分。

$ docker inspect --format '{{ .HostConfig.LogConfig }}' redis-server
{json-file map[]}
$ docker inspect --format '{{ .HostConfig.LogConfig }}' redis-syslog
{syslog map[]}
$ docker inspect --format '{{ .HostConfig.LogConfig }}' redis-none
{none map[]}
相关文章
|
Docker 容器
《Docker公司在金融行业落地实践》电子版地址
Docker公司在金融行业落地实践
106 1
《Docker公司在金融行业落地实践》电子版地址
|
缓存 JSON NoSQL
公司要新招美女跟我学docker,你来吗?(1)
公司要新招美女跟我学docker,你来吗?(1)
|
Docker 容器
|
Kubernetes 供应链 安全
Docker Desktop 向大公司宣告收费,网友大呼:是时候弃用了
在容器引擎 Docker 诞生的 8 年间,其与开源的容器编排 Kubernetes 共同推动容器技术在云计算领域的应用,也让自身在全球范围内受到了广泛的关注。可以说,做过云计算开发的程序员,十有八有学过 Docker 技术。 不过,近日 Docker 官方宣布一项新的动作,即将产品订阅划分为个人、专业、团队和商业不同版本,对于这样做的原因,官方称是为开发者所依赖的生产力和协作提供了业务所需的规模、安全性和可信内容,由此以可持续性的方式为 Docker 提供服务。
|
Ubuntu 应用服务中间件 Go
公司要新招美女跟我学docker,你来吗?(4)
公司要新招美女跟我学docker,你来吗?(4)
|
负载均衡 NoSQL JavaScript
公司要新招美女跟我学docker,你来吗?(3)
公司要新招美女跟我学docker,你来吗?(3)
|
关系型数据库 MySQL 数据库
公司mysql docker容器挂了,数据丢失,老板要起诉我。。
公司mysql docker容器挂了,数据丢失,老板要起诉我。。
527 0
公司mysql docker容器挂了,数据丢失,老板要起诉我。。
|
运维 Kubernetes 网络协议
Docker容器基础(二) - Docker公司的入场
Docker容器基础(二) - Docker公司的入场
139 0
Docker容器基础(二) - Docker公司的入场
|
Kubernetes Cloud Native 网络协议
Docker 容器实战 (二) :“ 鲸鱼” 公司粉墨登场
随着 PaaS 深入人心,Cloud Foundry 为首的传统 PaaS,开始蓄力基础设施领域的平台化和 PaaS 化,于是发现了 PaaS 中的问题 。本文将为大家讲解 Docker 的崛起之路。
947 0
Docker 容器实战 (二) :“ 鲸鱼” 公司粉墨登场
|
Devops 容器 Docker
Docker公司DevOps领军人物John Willis:DevOps最佳实践
本文主要从为什么要用DevOps开始谈起,接着分享DevOps的三种方式,着重分析第一种方式,包括Immutable Service Delivery的Devops (Faster)、Docker (Effective) 、Supply Chain (Reliable),最后浅谈了第二种方式。
594 0

热门文章

最新文章