Docker 入门

安装

安装步骤可以直接参考官方文档:

镜像加速

从 Docker Hub 上拉取镜像可能会比较慢,可以使用国内的一些镜像加速器服务:

CentOS、Ubuntu 可以在/etc/docker/daemon.json中配置镜像加速器:

{
  "registry-mirrors": [
    "https://hub-mirror.c.163.com",
    "https://mirror.baidubce.com"
  ]
}

Windows 则可以在Settings -> Docker Engine -> 右侧 JSON中配置上边的内容。

优势

传统的虚拟机需要实现硬件资源的虚拟化,而 Docker 直接使用物理机上的硬件资源;新建一个容器时不需要像虚拟机那样重新加载一个操作系统内核,而直接使用宿主机的操作系统内核;因此 Docker 更加的轻量级、运行效率更高!

启停命令

CentOS 下 一些 Docker 常用的启停命令:

  • 启动:systemctl start docker
  • 停止:systemctl stop docker
  • 重启:systemctl restart docker
  • 开机启动:systemctl enable docker
  • 查看状态:systemctl status docker

镜像(Image)

Docker 中的镜像是一个特殊的分层文件系统,主要提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,是只读的,其内容在构建之后也不会被改变。

Docker 在设计镜像时,利用 Union FS(联合文件系统)技术,将其设计为分层存储的架构,分层存储的特点使得镜像复用、定制变的更为容易。可以用现有的镜像为基础层,来添加新的层,以定制自己所需的内容。镜像是逐层构建的,前一层是后一层的基础,每一层构建完就不会再发生改变。

https://docs.docker.com/engine/reference/commandline/image/

  • 列出已下载的镜像:docker image ls、docker images

  • 只列出镜像 id:docker image ls -q

  • 拉取镜像:docker pull [镜像仓库地址] 仓库名[:标签]

    • 镜像仓库地址默认是Docker Hub(docker.io)
    • 仓库名由用户名/软件名组成,对于 Docker Hub 如果不指定用户名默认是library,也就是官方镜像
  • 搜索镜像:docker search 仓库名:标签

  • 查看镜像、容器、数据卷、缓存占用的空间:docker system df

  • 删除指定镜像:docker image rm 仓库名[:标签]/镜像id

  • 删除无用镜像:docker image prune

  • 保存、加载镜像:

    • docker save 仓库名[:标签]/镜像ID > 文件名.tar,将镜像保存为文件,会保存该镜像的的所有历史记录
    • docker load 文件名.tar,从文件加载镜像,会恢复镜像名、标签等信息
  • 制作镜像:docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]],将容器保存为镜像

    • OPTIONS 可以指定-a(作者信息);-m(提交信息)
    • CONTAINER 可以是容器名、容器ID
    • [REPOSITORY[:TAG]],生成镜像的名字、版本等
    • 最终的镜像会添加大量无关内容,导致镜像体积大;外界无法知道镜像的制作过程,执行了那些命令;所以一般不会使用该命令制作镜像,而是使用Dockerfile

容器(Container)

镜像和容器的关系,类似面向对象程序设计中的类和实例,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。

容器的本质进程,它运行在自己的独立的命名空间。容器可以拥有自己的文件系统、网络配置、进程空间等,可以看做是一个简易的 Linux 环境。容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样。这种特性使得容器封装的应用比直接在宿主运行更加安全。也因为这种隔离的特性,很多人初学 Docker 时常常会混淆容器和虚拟机。

容器运行时,会以镜像为基础层,在其上创建一个当前容器的运行时需要的存储层,容器存储层的生命周期和容器一样,任何保存于容器存储层的信息都会随容器删除而丢失。

根据 Docker 的最佳实践,容器不应该向其存储层内写入任何数据,容器存储层要保持无状态化。所有的文件写入操作,都应该使用数据卷(Volume)或者绑定宿主目录,其性能和稳定性更高。数据卷的生命周期独立于容器,因此容器删除或者重新运行之后,数据却不会丢失。

https://docs.docker.com/engine/reference/commandline/container/

  • 启动容器: docker run [OPTIONS] IMAGE [COMMAND] [ARG...],OPTIONS 常用的参数如下:
    • --name="容器名",给容器指定一个名称,不指定则随机分配
    • -d,在后台运行容器、并返回容器 ID,也称作守护状态运行
    • -i,以交互模式运行容器,通常和 -t 一起使用
    • -t,给容器重新分配一个伪输入终端,通常和 -i 一起使用
    • -P/-p,指定端口映射,详细内容见网络部分

使用 ubuntu 镜像以交互模式启动一个容器,并在容器内执行 /bin/bash 命令,得到一个交互式终端,退出终端可以使用exit

docker run -it ubuntu:18.04 /bin/bash
  • 列出指定容器:docker ps [OPTIONS],OPTIONS 常用的参数如下:

    • -a,列出当前所有运行的容器、历史上运行过的容器
    • -l,列出最近创建的容器
    • -n,列出最近创建的 n 个容器
    • -q,可以上前几个参数配合使用,只显示容器编号
  • 退出容器:在容器的交互模式下,退出终端

    • exit,会停止容器的运行
    • ctrl + q + p,不会停止容器
  • 停止容器:docker stop 容器ID/容器名

  • 启动停止运行的容器:docker start 容器ID/容器名

  • 重启容器:docker restart 容器ID/容器名

  • 强制停止容器:docker kill 容器ID/容器名

  • 删除停止运行的容器:docker rm 容器ID/容器名,删除运行中的容器需要添加-f

  • 查看容器日志:docker logs -f 容器ID/容器名

  • 进入容器:使用 -d 参数启动的后台运行容器,使用如下命令可进入交互终端:

    • docker attach 容器ID/容器名,执行exit会导致容器停止
    • docker exec -it 容器ID/容器名 /bin/bash,执行exit不会停止容器
  • 容器内拷贝文件到宿主机:docker cp 容器ID:容器内路径 目标主机路径,反过来拷贝也是类似的

  • 导入、导出容器快照:

    • docker export 容器ID/容器名 > 文件名.tar,导出容器快照(容器文件系统)到指定文件,会丢失所有元数据和历史记录,仅保存容器当时的状态
    • cat 文件名.tar | docker import - 用户名/镜像名:镜像版本号,从容器快照文件导入新镜像,可以指定镜像名、标签等信息
    • docker import URL,从 URL 导入镜像

数据存储

默认情况下,容器内产生的数据存储在其内部的可写层,其它进程很难访问这些数据,或者将其移动到其它地方,而且数据会随着容器的删除而丢失。容器内的可写存储层需要的存储驱动使用了联合文件系统,相比直接将数据存在主机目录性能也会差一些。

https://docs.docker.com/storage/

Docker 提供了如下两种方式将容器数据存储到宿主机上,也称作目录挂载:

  • Volumes,数据卷,将容器数据存储到由 Docker 管理的宿主机目录中(Linux 上是 /var/lib/docker/volumes/),它和宿主机的核心功能隔离,一个数据卷可以挂载到多个容器,实现容器间数据共享,这也是 Docker 推荐的方式。挂载时只需要指定数据卷的名称,适合挂载数据库等。
docker run -d -p 8008:80 --name web -v nginx:/usr/share/nginx/html nginx

通过-v命令将名为nginx的数据卷挂载到容器的/usr/share/nginx/html目录,如果数据卷不存在则会隐式创建,也可以显示创建,docker volume create xxx。此时如果数据卷为空则挂载到的容器目录中的数据会被复制到数据卷中;如果数据卷不为空则数据卷中的数据会覆盖容器目录的数据。我们可以根据需要配置多组-v命令。

也可以使用--mount命令,但如果数据卷不存在会报错。

  • Bind mounts,可以将数据存储在宿主机上的任意目录,挂载时需要指定宿主机上目录的绝对路径,也可以挂载到多个容器上,适合挂载配置文件等。
docker run -d -p 8008:80 --name web -v /opt/software/nginx:/usr/share/nginx/html nginx

同样使用-v命令,这里需要指定宿主机目录的绝对路径,如果目录不存在会自动创建;注意,宿主机目录的数据会直接覆盖容器目录的数据,这里和数据卷是有区别的。这里也可以使用--mount指令。

Dockerfile

Dockerfile 是用来构建 Docker 镜像的文本文件,其中包含了一条条的指令,每一条指令(指令的内容描述了该层应当如何构建)会构建镜像的一层。

https://docs.docker.com/engine/reference/builder/

Dockerfile 指令:
  • FROM,指定基础镜像,FROM 是必需的指令,并且必须是第一条指令;除了指定现有镜像为基础镜像外,还可以指定名为scratch的特殊镜像,它表示不以任何镜像为基础,接下来所写的指令将作为镜像第一层开始存在
  • RUN,用来执行命令行命令,通常用于安装应用和软件包,有两种格式:
    • shell 格式:RUN <命令>,类似直接在命令行输入命令,推荐使用该格式
    • exec 格式:RUN ["可执行文件", "参数1", "参数2"],类似函数调用的形式
  • EXPOSE,容器运行时对外暴露的端口,格式为EXPOSE <端口1> [<端口2>...],就是-p <宿主端口>:<容器端口>中的容器端口
  • WORKDIR,指定容器创建后,终端登录进来的默认工作目录,不存在会自动创建,格式为WORKDIR <工作目录路径>
  • USER,指定以什么样的用户身份去执行镜像,默认是 ROOT 用户,格式为USER <用户名>[:<用户组>]
  • ENV,设置环境变量,可以在其它指令中使用($key),格式为ENV <key> <value>或者ENV <key>=<value>
  • VOLUME,定义匿名数据卷,防止运行时用户忘记将需要的文件目录挂载为数据卷,当然运行容器时也可以覆盖这个挂载设置
  • COPY,将宿主机下的文件拷贝到镜像,使用 COPY 指令,源文件的各种元数据都会保留,比如读、写、执行权限、文件变更时间等。有两种格式(--chown=<user>:<group> 选项来改变文件的所属用户及所属组):
    • COPY [--chown=<user>:<group>] <源路径>... <目标路径>
    • COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]
  • ADD,将宿主机下的文件拷贝到镜像,会自动下载 URL、解压 tar 压缩包,格式和 COPY 指令基本一样
  • CMD,指定容器主进程的启动程序、参数,注意,执行 docker run 时镜像名/ID 后的命令会替换 CMD 的配置,CMD 有两种格式:
    • shell 格式:CMD <命令>
    • exec 格式:CMD ["可执行文件", "参数1", "参数2"...],推荐使用该格式
  • ENTRYPOINT,作用和 CMD 一样,都是指定容器主进程的启动程序、参数,但是执行 docker run 时镜像名/ID 后面的命令不会覆盖掉 ENTRYPOINT 配置的内容,而且后面的命令会作为参数传递给 ENTRYPOINT 指定的启动程序
    • ENTRYPOINT 也有 shell 和 exec 两种格式,和 CMD 类似
    • 如果 ENTRYPOINT 需要指定变化的参数,可以结合 CMD 一起使用,此时 CMD 的作用发生了变化不再是运行启动程序,而是将 CMD 的内容作为动态参数传递给 ENTRYPOINT
FROM centos

ENV MYPATH /usr/local
WORKDIR $MYPATH

# CentOS 8停止更新后,使用yum安装程序的时候会报错,需要做如下修改
RUN cd /etc/yum.repos.d/ \
    && sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* \
    && sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-* \
    && wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-vault-8.5.2111.repo \
    && yum clean all \
    && yum makecache
# 安装vim
RUN yum -y install vim
# 安装ifconfig
RUN yum -y install net-tools
# 安装java8,以及lib库
RUN yum -y install glibc.i686
RUN mkdir /usr/local/java
ADD jdk-8u301-linux-x64.tar.gz /usr/local/java
# 配置java环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_301
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
ENV PATH $JAVA_HOME/bin:$PATH

EXPOSR 8081

CMD echo $MYPATH
CMD echo "---------success----------"
CMD /bin/bash
构建镜像

一般我们会创建一个名为Dockerfile的文件,然后通过上边的指令编写构建镜像的脚本,最后通过如下命令完成就像的构建:

docker build -t 镜像名:TAG .

注意命令最后边有一个.符号,表示执行指令的当前目录,也就是上下文目录,docker build 命令会将该目录下的内容打包交给 Docker 引擎以帮助构建镜像。

默认情况下,如果不额外指定 Dockerfile 文件的话,会将上下文目录下的名为 Dockerfile 的文件作为 Dockerfile,当然也可以用-f ../Dockerfile.txt参数指定 Dockerfile 的文件名以及相对上下文路径的存放目录。

一般来说,应该将 Dockerfile 文件放在一个空目录下或者项目根目录下。如果该目录下没有所需文件,那么应该把所需文件复制一份过来。如果目录下有些文件不希望构建时上传给 Docker 引擎,那么可以用 .gitignore 一样的语法写一个.dockerignore文件来忽略掉它们。

网络

外部访问容器

要从外部访问容器内运行的网络应用时,可以通过 -P 或 -p 参数来指定端口映射:

  • -P,Docker 会随机映射一个可用的宿主机端口到内部容器开放的网络端口
  • -p,指定需要映射的端口,一个指定端口上只可以绑定一个容器。支持的格有:
    • hostPort:containerPort,映射到本地的指定端口
    • ip:hostPort:containerPort,映射到指定地址的指定端口
    • ip::containerPort,映射到指定地址的任意端口
  • docker port <container name/id> containerPort,查看指定容器端口映射的外部端口配置
容器互联
  • docker network create [-d 网络类型] <name>,创建网络,网络类型默认为bridge
  • docker network ls,查看已有网络
  • docker network rm <name/NETWORK ID>,删除指定网络

我们可以创建一个网络,然后在运行容器时使用--network指定要连接到的网络,这样不同容器可以运行在同一网络,实现容器间的互联:

docker network create -d bridge net007
docker run -d -p 8008:80 --name web -v nginx:/usr/share/nginx/html  --network net007 nginx
docker run -d -p 8008:80 --name web2 -v nginx:/usr/share/nginx/html  --network net007 nginx

这样可以通过 ping 命令来验证两个容器是否可以互相通信,例如进入 web 容器执行ping web2。需要先安装 ping:

apt-get update
apt install iputils-ping

运行容器时如果不指定网络,容器间也是可以通过 ip 互联的,但是容器内的 ip 可能会变化,所以运行容器时可以指定网络然后用容器名通信。

Docker compose

Compose 项目是 Docker 官方的开源项目,用于定义和运行多个容器的工具,实现对 Docker 容器集群的快速编排,简单的理解就是处理需要多个容器相互配合来完成某项任务的场景。

Compose 中有两个重要的概念:

  • 服务 (service):一个应用的容器
  • 项目 (project):由一组关联的应用容器组成的一个完整业务单元,在docker-compose.yml文件中定义。

Compose 的默认管理对象是项目,通过子命令对项目中的一组容器进行便捷地生命周期管理。

例如一个 Web 项目,除了 Web 服务本身,可能还需要MySQL、Redis、Nginx等服务,使用 Compose 可以编写一个docker-compose.yml文件来定义一组相关联的应用容器为一个项目,控制容器启动的顺序,实现管理多个应用容器等需求,而不用单独去维护每个容器。

安装:https://docs.docker.com/compose/install/compose-plugin/

编写 Compose 模板文件

https://docs.docker.com/compose/compose-file/
模板文件的默认名称是docker-compose.yml,即一个YAML格式的文件。

version: "3"

services:
  docker_test:
    image:  docker_test:v1
    container_name: dtv1
    ports:
      - "7001:7001"
    volumes:
      - docker_test_data:/tmp
    networks:
      - net007
    depends_on:
      - redis
      - mysql
  
  redis:
    image: redis:6.0.8
    ports:
      - "6379:6379"
    volumes:
      - /opt/software/edis/redis.conf:/etc/redis/redis.conf
      - redis_data:/data
    networks:
      - net007
    command: redis-server /etc/redis/redis.conf
  
  mysql:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: '123456'
      MYSQL_ALLOW_EMPTY_PASSWORD: 'no'
      MYSQL_DATABASE: 'mytest'
      MYSQL_USER: 'user01'
      MYSQL_PASSWORD: '123456'
    ports:
      - "3306:3306"
    volumes:
      - mysql_data:/var/lib/mysql
      - /opt/software/mysql/conf/my.cnf:/etc/my.cnf
      - /opt/software/mysql/init:/docker-entrypoint-initdb.d
    networks:
      - net007
    command: --default-authentication-plugin=mysql_native_password # 解决外部无法访问

networks:
  net007:

volumes:
  docker_test_data:
  redis_data:
  mysql_data:

docker-compose.yml文件目录下运行 Compose 项目:

docker-compose up
  • version,指定 Compose 模板文件版本,和 Docker 版本有对应关系
  • services,配置具体的服务,我们这里设计三个服务 docker_test(一个 SpringBoot 服务)、redis、mysql。注意每个服务都必须通过 image 指令指定镜像或者用build指令指定 Dockerfile 来自动构建生成镜像,这里使用第一种。
  • networks,配置容器连接的网络,文件最后的 networks 则是先创建网络
  • image,指定服务的镜像
  • container_name,指定容器名,默认使用项目名称_服务名称_序号的格式
  • ports,配置端口映射
  • volumes,将容器数据挂载到宿主机。如果使用数据卷方式则需要先创建数据卷,例如文件最后的 volumes;或者直接挂载到宿主机的指定目录
  • depends_on,设置服务间的依赖关系,被依赖的
  • command,覆盖容器启动后默认执行的命令
  • environment,配置容器内的环境变量

docker_test 服务对应的 Dockerfile 镜像构建文件:

FROM java:8
VOLUME /tmp # 定义匿名数据卷,SpringBoot使用的内嵌Tomcat容器默认将/tmp作为工作目录
COPY docker_test-1.0-SNAPSHOT.jar /docker_test.jar
ENTRYPOINT ["java", "-jar", "docker_test.jar"]
EXPOSE 7001

构建镜像:

docker build Dockerfile  -t docker_test:v1 .
Compose 命令

https://docs.docker.com/compose/reference/

Compose 的大部分命令操作的对象既可以是项目本身,也可以指定为项目中的服务,如果没有特别指定则命令操作的对象将是项目,也就是项目中所有的服务都会受到命令影响。命令的基本格式如下:
docker-compose [-f=<arg>...] [options] [COMMAND] [ARGS...]

  • -f,指定 Compose 文件名,默认的文件名为docker-compose.yml
  • -p,指定项目名,默认为所在目录名称

以下是一些常用的命令,一般在模板文件目录下执行:

  • docker-compose config,验证 Compose 文件格式是否正确
  • docker-compose up [OPTIONS] [SERVICE...],这个命令很重要,可以完成构建镜像,创建、启动服务容器,并关联服务相关容器等一系列操作。默认情况,docker compose up启动的容器都在前台运行,同时如果服务容器已经存在,它将会尝试停止容器,然后重新创建。OPTIONS 常用参数:
    • -d,在后台运行服务容器。
    • --no-deps,重新部署指定服务
    • --force-recreate,强制重新创建容器
    • --no-recreate,如果容器已经存在了,则不重新创建;不能和 --force-recreate 同时使用。
  • docker-compose ps,列出项目中的容器
  • docker-compose restart [SERVICE...],重启项目中的容器,不指定服务名则重启全部
  • docker-compose stop [SERVICE...],停止运行的容器
  • docker-compose exec [SERVICE] sh,进入指定容器
  • docker-compose logs [-f] [SERVICE],查看容器的日志
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容

  • 基本概念 镜像Docker 镜像就是一个只读的模板,镜像可以用来创建 Docker 容器 容器容器是从镜像创建的运...
    巨子联盟阅读 7,479评论 0 3
  • Docker概念 Docker 是世界领先的软件容器平台。开发人员利用 Docker 可以消除协作编码时“在我的机...
    三也视界阅读 933评论 0 2
  • 序言 从docker的出现以来,它就成为了互联网公司的宠儿。换句话说现在牛逼的互联网公司的架构系统不使用在 Doc...
    天野浪子阅读 221评论 0 0
  • Docker入门 1. 简介 (1)容器(Container) vs 虚拟机(Virtual Machine) 容...
    四毛荷东阅读 567评论 0 1
  • 上一篇 / 目录 / 下一篇 英文原文在这里:https://docs.docker.com/get-starte...
    谈飞阅读 1,575评论 0 12