参考: https://hub.docker.com/

  • Docker 最初 dotCloud 公司内部的一个业余项目

  • Docker 基于 Go 语言

  • Docker 项目的目标是实现轻量级的操作系统虚拟化解决方案

  • Docker 的基础是 Linux 容器(LXC)等技术

  • Docker 容器的启动可以在秒级实现,这相比传统的虚拟机方式要快得多

  • Docker 对系统资源的利用率很高,一台主机上可以同时运行数千个 Docker 容器

下面的图片比较了 Docker 和传统虚拟化方式的不同之处,可见容器是在操作系统层面上实现虚拟化,直接复用本地主机的操作系统,而传统方式则是在硬件层面实现。

容器除了运行其中应用外,基本不消耗额外的系统资源,使得应用的性能很高,同时系统的开销尽量小。传统虚拟机方式运行 10 个不同的应用就要起 10 个虚拟机,而Docker 只需要启动 10 个隔离的应用即可。

主要优势为:

  • 更快速的交付和部署 - 容器成为了最小单位

  • 更高效的虚拟化 - 内核级虚拟化

  • 更轻松的迁移和拓展

  • 更简单的管理

1 安装

官方网站提供了 Mac, Linux 和 Windows 版本的安装教程。我们只要跟着官方文档即可,这里不再赘述。

不过需要提一下 Kitematic 这个图形化工具(官方给出的定义是 Visual Docker Container Management on Mac & Windows),对于熟悉和了解 Docker 是很好的帮助,大家可以体验一下。

守护进程

运行 Docker 守护进程时,可以用 -H 来改变绑定接口的方式,比如

sudo /usr/bin/docker -d -H tcp://0.0.0.0:2375

如果不想每次都输入这么长的命令,需要加入以下环境变量

export DOCKER_HOST="tcp://0.0.0.0:2375"

图形用户界面

虽然我们可以用命令来控制 docker,但是如果能有一个 web 管理界面,操作什么的会方便很多,比较常见的有

  • Shipyard

  • Potainer

2 基本概念

基本概念主要有三个:

  • 镜像(Image)

    • 一个只读的模板,镜像可以用来创建 Docker 容器

    • 用户基于镜像来运行自己的容器。镜像是基于 Union 文件系统的层式结构

    • 可以简单创建或更新现有镜像,或者直接下载使用其他人的。可以理解为生成容器的『源代码』

  • 容器(Container)

    • 容器是从镜像创建的运行实例,在启动的时候创建一层可写层作为最上层(因为镜像是只读的)

    • 可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台

    • 可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序

  • 仓库(Registry)

    • 集中存放镜像文件的场所,可以是公有的,也可以是私有的

    • 最大的公开仓库是 Docker Hub

    • 国内的公开仓库包括 Docker Pool 等

    • 当用户创建了自己的镜像之后就可以使用 push 命令将它上传到公有或者私有仓库,这样下次在另外一台机器上使用这个镜像时候,只需要从仓库上 pull 下来就可以了

    • Docker 仓库的概念跟 Git 类似,注册服务器可以理解为 GitHub 这样的托管服务

另外 Docker 采用的是客户端/服务器架构,客户端只需要向 Docker 服务器或守护进程发出请求即可完成各类操作。那么问题来了,我们能用 Docker 来做什么呢?我们可以:

  • 统一、优化和加速本地开发和构建流程

  • 保证不同的环境中可以得到相同的运行结果

  • 创建隔离环境用于测试

Docker 可以提供的隔离有:

  • 文件系统隔离:每个容器都有自己的 root 文件系统

  • 进程隔离:每个容器都运行在自己的进程环境中

  • 网络隔离:容器间的虚拟网络接口和 IP 地址都是分开的

  • 资源隔离和分组:使用 cgroups 将 CPU 和内存之类的资源独立分配给每个 Docker 容器

3 常用命令

  • 查看 docker 状态 sudo docker info

  • 查看系统中正在运行的容器的列表 docker ps

    • 加上 -a 可以列出所有容器

    • 加上 -l 可以列出最后一次运行的容器

一个简单的例子

接下来我们用一个简单的例子来体验下 docker

4 容器小介绍

容器是独立运行的一个或一组应用,以及它们的运行态环境。对应的,虚拟机可以理解为模拟运行的一整套操作系统(提供了运行态环境和其他系统环境)和跑在上面的应用。

启动容器有两种方式,一种是基于镜像新建一个容器并启动,另外一个是将在终止状态(stopped)的容器重新启动。因为 Docker 的容器实在太轻量级了,很多时候用户都是随时删除和新创建容器(对于初级应用来说后者更方便)。

当利用 docker run 来创建容器时,Docker 在后台运行的标准操作包括:

  • 检查本地是否存在指定的镜像,不存在就从公有仓库下载

  • 利用镜像创建并启动一个容器

  • 分配一个文件系统,并在只读的镜像层外面挂载一层可读写层

  • 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去

  • 从地址池配置一个 ip 地址给容器

  • 执行用户指定的应用程序

  • 执行完毕后容器被终止

可以利用 docker start 命令,直接将一个已经终止的容器启动运行。

5 运行容器

现在,我们来创建一个 ubuntu:14.04 的容器

docker run ubuntu:14.04 /bin/echo 'Hello wdx!'

(结果如下图所示)

可以看到正确输出了我们的 “Hello wdx!”

接下来,我们用 docker run -t -i ubuntu:14.04 /bin/bash 可以启动一个 bash 终端用来交互。参数的意思是:

  • -t 选项让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上

  • -i 则让容器的标准输入保持打开

我们可以输入一些命令来测试

容器的核心为所执行的应用程序,所需要的资源都是应用程序运行所必需的。除此之外,并没有其它的资源。我们用 ps 或 top 在伪终端中查看进程信息,可以看到只有我们运行的进程,没有其他花里胡哨的(上图最后一条命令)

试一试如下命令

  • cat /etc/hosts

  • ip a

  • ps -aux

  • cd ~ && echo "hello wdx" > hello.txt && cat hello.txt

(细心的同学可能会发现这里的输出暗藏玄机)

操作完成后,输入 exit 便可以退出这个 ubuntu 容器。退出之后这个容器依然存在,我们可以用 docker ps -l来看看:

每个容器有一个 Container ID 和 Name,我们一般就是通过这俩来定位一个容器的。


6 镜像

我们可以使用 docker pull 命令从仓库中获取所需要的镜像。比如说

sudo docker pull ubuntu:12.04

相当于

sudo docker pull registry.hub.docker.com/ubuntu:12.04

即从注册服务器 registry.hub.docker.com中的 ubuntu 仓库来下载标记为12.04 的镜像。

如果想从其他仓库注册服务器下载,需要输入完成的地址,例如:

sudo docker pull dl.dockerpool.com:5000/ubuntu:12.04

下载完成之后就可以使用该镜像了,比如下面的语句就会创建容器,其中运行 bash

sudo docker run -t -i ubuntu:12.04 /bin/bash

可以使用 dokcer images 来显示本地已有的镜像,如下

具体字段的意思一目了然,这里不再赘述。然后我们来运行官方例子 whalesay 镜像。

7 运行镜像

打开浏览器,进入 Docker Hub

搜索 whalesay 这个镜像,就可以看到结果,点进去可以看到详细内容(基于 Ubuntu)

然后我们来运行一下,使用命令

docker run docker/whalesay cowsay boo

其中 cowsay 是要运行的命令,后面的 boo 是参数。

Docker 会先在本地查找有没有镜像,如果没有就从仓库中下载,具体的运行结果是:

[root@localhost ~]# docker run docker/whalesay cowsay boo_____
< boo >----- \\\     ##        .            ## ## ##       ==            ## ## ## ##      ===            /""""""""""""""""___/ ===        ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ /  ===- ~~~   \______ o          __/            \    \        __/             \____\______/
[root@localhost ~]#

也可以让鲸鱼说不同的话,比如:

[root@localhost ~]# docker run docker/whalesay cowsay test______
< test >------ \\\     ##        .            ## ## ##       ==            ## ## ## ##      ===            /""""""""""""""""___/ ===        ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ /  ===- ~~~   \______ o          __/            \    \        __/             \____\______/

8 制作镜像

如果想要制作自己的镜像,需要自己写 Dockerfile。具体步骤如下

  1. 创建一个文件夹 mkdir wdxtub; cd wdxtub,构造镜像所需的所有东西都会放在这个文件夹中

  2. 创建一个名为 Dockerfile 的文件 gedit Dockerfile

  3. 添加第一句话 FROM docker/whalesay:latest,表示我们的镜像以 whalesay 为基础

  4. 添加需要运行的命令,如 RUN apt-get -y update && apt-get install -y fortunesfortunes 这个程序会输出名言警句)

  5. 通过 CMD 指定镜像载入之后需要执行的命令,如 CMD /usr/games/fortune -a | cowsay

  6. 保存并关闭 Dockerfile

  7. 使用 sudo docker build -t wdx-whale . 来构造镜像,简单来说就是用 Dockerfile 中的内容按步骤构造

  8. 使用 docker images 应该就可以看到我们新创建的镜像

然后我们就可以运行一下看看

docker run wdx-whale

还有更贱的(感觉可以玩一天)

如果想要把自己的镜像上传到网上,就需要注册一个 Docker Hub 帐号,然后点击 Create Repository,这里我创建了一个名为 allenshen / myrepo123的公用仓库。

接下来我们需要打上 tag,目前 docker images 的情况是:

[root@localhost ~]# docker images|head -6
REPOSITORY                                                               TAG                 IMAGE ID            CREATED             SIZE
myiso                                                                    latest              e6afc78e32c1        30 minutes ago      247MB
myiso                                                                    newest              e6afc78e32c1        30 minutes ago      247MB
registry.cn-beijing.aliyuncs.com/bbt_k8s/kube-proxy-amd64                v1.6.2              7a1b61b8f5d4        2 years ago         109MB
gcr.io/google_containers/kube-proxy-amd64                                v1.6.2              7a1b61b8f5d4        2 years ago         109MB

You may push a new image to this repository using the CLI:

docker tag local-image:tagname new-repo:tagname
docker push new-repo:tagname

To push a new tag to this repository:

docker push allenshen1986/myrepo123:tagname

You need to include the namespace for Docker Hub to associate it with your account.
The namespace is the same as your Docker Hub account name.
You need to rename the image to YOUR_DOCKERHUB_NAME/docker-whale.

记住我们的 IMAGE ID e6afc78e32c1。用以下命令打 tag

docker tag e6afc78e32c1 allenshen/myiso

然后再 docker images 一次:

[root@localhost ~]# docker images|head -6
REPOSITORY                                                               TAG                 IMAGE ID            CREATED             SIZE
allenshen/myiso                                                      latest              e6afc78e32c1        36 minutes ago      247MB
myiso                                                                    latest              e6afc78e32c1        36 minutes ago      247MB
myiso                                                                    newest              e6afc78e32c1        36 minutes ago      247MB
gcr.io/google_containers/kube-proxy-amd64                                v1.6.2              7a1b61b8f5d4        2 years ago         109MB
registry.cn-beijing.aliyuncs.com/bbt_k8s/kube-proxy-amd64                v1.6.2              7a1b61b8f5d4        2 years ago         109MB

然后用这个命令登录

docker login --username=yourhubusername

对于我来说就是

docker login --username=***

成功之后大概是这样:

[root@localhost ~]# docker login --username=allenshen
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-storeLogin Succeeded

然后就可以 push 上去了 ocker push allenshen/myiso,像下面这样

[root@localhost ~]# docker push allenshen/myiso
The push refers to repository [docker.io/allenshen/myiso]
5f70bf18a086: Pushed
d061ee1340ec: Pushed
d511ed9e12e1: Pushed
091abc5148e4: Pushed
b26122d57afa: Pushed
37ee47034d9b: Pushed
528c8710fd95: Pushed
1154ba695078: Pushed
latest: digest: sha256:eadf17373c1314cc43f4b68bb84a2579f7d8f3e9931062b823d49f96b5437f09 size: 2402

为了测试 pull 自己的镜像,我们先把本地上的 myiso 镜像删掉:

docker rmi -f wdxtub/wdx-whale; docker rmi -f wdx-whale

(如果有其他的用不着的也都删掉),最后剩下(上课要用的镜像):

接着来运行一下

docker run wdxtub/wdx-whale

9 管理镜像

我们可以把镜像导出到本地文件,使用 docker save 命令即可,比如针对我现在有的镜像 wdxtub/wdx-whale(id:26ac9649d7da),可以这样:

docker save -o wdx-local-whale.tar wdxtub/wdx-whale

如果要载入的话,使用下面的命令即可(会载入相关的元数据信息)

docker load --input wdx-local-whale.tar# 或者docker load < wdx-local-whale.tar

在删除镜像之前要先用 docker rm 删掉依赖于这个镜像的所有容器.

sudo docker rmi $(docker images -q -f "dangling=true")

镜像的实现原理

Docker 镜像是怎么实现增量的修改和维护的? 每个镜像都由很多层次构成,Docker 使用 Union FS 将这些不同的层结合到一个镜像中去。

通常 Union FS 有两个用途, 一方面可以实现不借助 LVM、RAID 将多个 disk 挂到同一个目录下,另一个更常用的就是将一个只读的分支和一个可写的分支联合在一起,Live CD 正是基于此方法可以允许在镜像不变的基础上允许用户在其上进行一些写操作。 Docker 在 AUFS 上构建的容器也是利用了类似的原理。

10 容器启动

举个例子,

后台运行

更多的时候,需要让 Docker在后台运行而不是直接把执行命令的结果输出在当前宿主机下。此时,可以通过添加 -d 参数来实现。

下面举两个例子来说明一下。

如果不使用 -d 参数运行容器

docker run ubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"

容器会把输出的结果(STDOUT)打印到宿主机上面

如果使用了 -d 参数运行容器

docker run -d ubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"

则显示是这样:

使用 docker logs containerid 可以查看输出,如:

使用 -d 参数启动后会返回一个唯一的 id,也可以通过 docker ps 命令来查看容器信息。容器是否会长久运行,是和docker run指定的命令有关,和 -d 参数无关

在使用 -d 参数时,容器启动后会进入后台。 某些时候需要进入容器进行操作,有很多种方法,包括使用 docker attach 命令或 nsenter 工具等。具体参考这里

11 终止与重新启动

使用 docker stop containerid 来终止容器。终止状态的容器可以用 docker ps -a 命令看到。

另外,docker restart containerid 命令会将一个运行态的容器终止,然后再重新启动它。

12 导入导出与删除

如果要导出本地某个容器,可以使用 docker export containerid 命令。

可以使用 docker import 从容器快照文件中再导入为镜像,例如

cat ubuntu.tar | sudo docker import - test/ubuntu:v1.0# 也可以通过指定 URL 或者某个目录来导入,例如docker import http://example.com/exampleimage.tgz example/imagerepo

用户既可以使用 docker load 来导入镜像存储文件到本地镜像库,也可以使用docker import 来导入一个容器快照到本地镜像库。这两者的区别在于容器快照文件将丢弃所有的历史记录和元数据信息(即仅保存容器当时的快照状态),而镜像存储文件将保存完整记录,体积也要大。此外,从容器快照文件导入时可以重新指定标签等元数据信息。

可以使用 docker rm 来删除一个处于终止状态的容器。如果要删除一个运行中的容器,可以添加 -f 参数。Docker 会发送 SIGKILL 信号给容器。

用 docker ps -a 命令可以查看所有已经创建的包括终止状态的容器,如果数量太多要一个个删除可能会很麻烦,用 docker rm $(docker ps -a -q) 可以全部清理掉。

注意:这个命令其实会试图删除所有的包括还在运行中的容器,不过就像上面提过的docker rm 默认并不会删除运行中的容器。

13 仓库

仓库(Repository)是集中存放镜像的地方。

一个容易混淆的概念是注册服务器(Registry)。实际上注册服务器是管理仓库的具体服务器,每个服务器上可以有多个仓库,而每个仓库下面有多个镜像。从这方面来说,仓库可以被认为是一个具体的项目或目录。例如对于仓库地址dl.dockerpool.com/ubuntu 来说,dl.dockerpool.com 是注册服务器地址,ubuntu是仓库名。

Docker 基础

Docker 支持 Windows/Linux/Mac/AWS/Azure 多种平台的安装,其中 Windows 需要 Win10+,Mac 需要 EI Captain+。Docker 是一个 C/S 架构的服务,安装好 docker 之后需要启动 docker 软件后才能使用 docker 命令。

Docker 主要有 Dockerfile, Image, Container, Repository 四个基本概念。通过 Dockerfile 我们可以生成 Docker Image(镜像)。自己制作的镜像可以上传到 Docker hub 平台,也可以从平台上拉去我们需要的镜像。当镜像拉到本地之后,我们就可以实例化这个镜像形成一个 Container(实例) 了。一个简单的镜像启动的命令是:

 

$ docker run [组织名称]/<镜像名称>:[镜像标签]`

其中除了镜像名称,其它的都是可选参数。组织名称不填默认为library,镜像标签不填则默认为latest。例如经典的启动一个 Hello World 镜像的过程如下:

可以看到当我实例化hello-world这个镜像的时候,docker 发现本地没有这个镜像会先去 Docker hub 远端拉取镜像,如刚才说的,默认是latest标签。拉取后就会实例化执行入口命令了。我们除了可以使用 Docker hub 查找我们需要的镜像之外,也可以使用docker search命令来查找。16年的一篇文章③显示,Docker hub 上的镜像包总量已经超过40万了,并且以每周4-5k的速度增长着。

下面我们就来看看如何运行一个 Nginx 容器实例:

 

$ docker run

-d

--rm

-p 8080:80

-v "$PWD/workspace":/var/www/hello.world

-v "$PWD/hello.world.conf":/etc/nginx/conf.d/hello.world.conf

nginx

使用docker run命令就能启动一个实例了,其中-p表示将本机的 8080 端口映射到镜像实例内的 80 端口,而-v表示将本地的$PWD/workspace文件夹映射到镜像实例里的/var/www/hello.world文件夹,后面的同理。最后再指定一下镜像名称,就能完成一次 Nginx 实例的启动了。此时访问http://hello.world:8080即可看到效果。

注:千万不要在容器实例中存储内容,实例销毁时实例内的所有内容都会被销毁,下次启动的时候又是全新的实例,内容不会保存下来。如果需要存储服务需要使用挂载卷或者外部存储服务。

Dockerfile

Dockerfile 是 Docker 比较重要的概念。它是 Docker 创建镜像的核心,它的出现给 Docker 提供了两大好处:

  1. 文本化的镜像生成操作让其方便版本管理和自动化部署

  2. 每条命令对应镜像的一层,细化操作后保证其可增量更新,复用镜像块,减小镜像体积

Dockerfile 的一些编写规则主要如下:

  1. 使用#来注释

  2. FROM 指令告诉 Docker 使用哪个镜像作为基础

  3. RUN 开头的指令会在创建中运行,比如安装一个软件包

  4. COPY 指令将文件复制进镜像中

  5. WORKDIR 指定工作目录

  6. CMD/ENTRYPOINT 容器启动执行命令

RUN 和 CMD/ENTRYPOINT 都是执行命令,区别在于 RUN 是在镜像构建过程中执行的,而 CMD/ENTRYPOINT 是在镜像生成实例的时候执行的,类似于 C/C++ 语言的头文件的正常代码的区别。而且后者在一个 Dockerfile 文件中只能有一个存在。CMD/ENTRYPOINT 的区别除了在写法上有区别之外,还有在docker run命令后增加 CMD 参数的情况下有区别(CMD会被复写)。一般建议使用 ENTRYPOINT 会更方便点。一个简单的 Node 命令行脚本的 Dockerfile 文件如下:

 

FROM mhart/alpine-node:8.9.3 LABEL maintainer="lizheming <i@imnerd.org>"

org.label-schema.name="Drone Wechat Notification"

org.label-schema.vendor="lizheming"

org.label-schema.schema-version="1.1.0"

WORKDIR /wechat

COPY package.json /wechat/package.json

RUN npm install --production --registry=https://registry.npm.taobao.org

COPY index.js /wechat/index.js

ENTRYPOINT [ "node", "/wechat/index.js" ]

这里我认为依赖是比较固定的,没有代码修改那么频繁,所以将其提前了。最终保证了所以越稳定的变化的命令至于上层,保证了每层打包出来的 Layer 能够尽可能的复用,而不会徒增镜像的大小。最后我们使用如下命令就可以完成一个 Docker 镜像的构建了:

 

$ docker build lizheming/drone-wechat:latest

参数和docker run是一样的。构建完成之后就可以开心的 push 到 Docker hub 上啦~

Docker Compose

以上我们说了下如何启动一个服务,但是我们都明白一个完整的项目肯定是不止依赖一个服务的,而 Docker 镜像的 ENTRYPOINT 只能设置一个,所以难道我们要使用docker run命令手动创建 N 个容器实例吗?为了解决这个问题,Docker Compose 就瞬时出现了。Docker Compose 是一款容器编排程序,使用 YAML 配置的形式将你需要启动的容器管理起来,免去我们需要多次执行docker run命令的烦恼。

Docker Compose 是使用 Python 开发的,它的安装非常的简单,直接pip install docker-compose就好了。安装完成之后分别使用up和stop命令可以启动和停止服务。一个简单的 docker-compose.yaml 配置文件大概如下:

 

version: "2"

services:

nginx:

depends_on:

- "php"

image: "nginx:latest"

volumes:

- "$PWD/src/docker/conf:/etc/nginx/conf.d"

- "$PWD:/home/q/system/m_look_360_cn"

ports:

- "8082:80"

container_name: "m.look.360.cn-nginx"

php:

image: "lizheming/php-fpm-yaf"

volumes:

- "$PWD:/home/q/system/m_look_360_cn"

container_name: "m.look.360.cn-php"

Docker Compose 的另外一个好处就是能够帮我们处理容器的依赖关系,在每个容器中会将容器的 IP 和服务的名称使用 hosts 的方式绑定,这样我们就能在容器中直接使用服务名称来接入对应的容器了。例如下面这个 Nginx 配置中的php:9000就是利用了这个原理。

 

server {

listen 80;

server_name dev.m.look.360.cn;

charset utf-8;

root /home/q/system/m_look_360_cn/public;

index index.html index.htm index.php;

error_page 500 502 503 504 /50x.html;

location = /50x.html {

root html;

}

# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000

#

location ~ .php$ {

fastcgi_pass php:9000;

#fastcgi_pass unix:/tmp/fcgi.sock;

fastcgi_index index.php;

}

}

Docker 相关

基于 Docker 容器虚拟化技术除了以上说的解决部署环境之外,还有一些其它的优点,例如:

  1. 基于 Docker 的 CI 持续集成和 CD 持续支付

  2. 基于 Kubernetes, Docker Swarm 的集群弹性扩容和缩容

CI/CD 对于现在的敏捷开发是非常重要的,自动化任务帮助我们节省很多不必要的开发时间浪费,具体可查看我之间的文章《基于Docker的CI工具》④。而 k8s 和 Docker Swarm 带来的弹性扩容和缩容让业务不在为流量问题而头疼。通过监控报警设置当出现峰值的时候自动扩容抗压,当出现低谷的时候自动去除多余的容器来节省成本,同时也将多余的资源给其它服务使用。

学习资料

  • 什么是 Docker ?https://cloud.tencent.com/developer/article/1005172

  • Docker 从入门到实践https://yeasy.gitbooks.io/docker_practice/

  • Docker compose 详解https://www.jianshu.com/p/2217cfed29d7

  • 深入浅出Dockerhttps://www.kancloud.cn/infoq/docker/79768

Docker 新手入门指南相关推荐

  1. Docker新手入门详细介绍

    Docker新手入门详细介绍 Docker 起源于 dotCloud 公司的内部项目,于 2013 年 3 月以 Apache 2.0 授权协议开源,主要项目代码在 GitHub 上进行维护,2013 ...

  2. Docker新手入门:基本用法

    Docker新手入门:基本用法 1.Docker简介 1.1 第一本Docker书 工作中不断碰到Docker,今天终于算是正式开始学习了.在挑选系统学习Docker以及虚拟化技术的书籍时还碰到了不少 ...

  3. mac 删除分区 command r 选择网络_Mac使用必看基础篇,Mac快捷键大全,mac新手入门指南...

    你是Mac新手吗?你对使用Mac电脑有疑问吗?你还不知道mac有哪些快捷键吗?别着急,来看看小编给大家准备的Mac使用必看基础篇--Mac快捷键大全,对于新手用户很有帮助哦!! 一.开机相关命令快捷键 ...

  4. Neo4j 新手入门指南

    Neo4j 新手入门指南 前言: 前段时间在公司实习有用到图数据库做一个小项目,就想着记录一下当时找到的比较有用的资料. 纯属入门学习啦,新手当作一个大纲来学习也可以! 感谢关注! 所有链接均在文章结 ...

  5. python pip-什么是pip?Python新手入门指南

    什么是 pip ?pip 是 Python 中的标准库管理器.它允许你安装和管理不属于 Python标准库 的其它软件包.本教程就是为 Python 新手介绍 pip. 通过本教程,你将学到: 1. ...

  6. 蓝桥云课之新手入门指南

    这是蓝桥云课学习人数最多的课程: 新手入门指南之玩转蓝桥云课 460896 人学过 27739 次评价 作者: 云课管理员 难度: 初级 综合评分: 9.4 复习一遍,里面共有3中课程模式: 第一种, ...

  7. Docker新手入门教程

    Docker新手入门教程 1.简介 Docker是一个开源的应用容器引擎:是一个轻量级容器技术: Docker支持将软件编译成一个镜像:然后在镜像中各种软件做好配置,将镜像发布出去,其他使用者可以直接 ...

  8. rust油桶用什么打_腐蚀rust新手入门指南 游戏新萌拿好不谢!

    川北在线核心提示:原标题:腐蚀rust新手入门指南 游戏新萌拿好不谢! 如何开始游戏? 巴拉巴拉那么多现在开始步入正轨吧! 点击find game 就进入了服务器列表,在这里你可以加入官方的服务器(热 ...

  9. 新手入门指南之玩转蓝桥云课

    新手入门指南之玩转蓝桥云课 文档1  你好,蓝桥云课 实验1 Linux 桌面环境使用指南 本实验采用的就是图形界面的 Linux 桌面环境.图形界面使用的是非常优秀的 Ubuntu Linux 操作 ...

最新文章

  1. fasterrcnn深度学习口罩检测
  2. 11.02T1 几何
  3. jinja2的url_for 和数据块
  4. 如何参与github上的开源项目?
  5. Apache(3)——配置文件里的各参数(1)
  6. Cookie中不能有空格_PHP 使用cookie
  7. 精选30道Java多线程面试题
  8. strcmp java_C语言中strcmp的实现原型
  9. Hibernate_2_Hibernate中对象状态及转化_一级缓存_Session详解_HQL/SQL/Criteria_一对多关系_级联操作
  10. 算法高级(43)-过滤垃圾邮件、短信?-朴素贝叶斯算法
  11. 让我们在Ubuntu 18.04上加密SSL证书来保护Nginx
  12. isag java_ISAG - WEB源码|JSP源码/Java|源代码 - 源码中国
  13. jdbc sql拼接字符串
  14. 读取pdf文字和excel写入操作
  15. 最小二乘法理解与应用
  16. ROS从入门到精通0-2:ROS简介、安装与常见问题
  17. 上海个人住房公积金复议材料
  18. iOS 更改webView文字颜色丶文字大小丶背景色的方法
  19. IP RAN基站回传中的三大组网方案
  20. h5是html语言吗,H5和HTML5是一样的吗

热门文章

  1. embarrass的用法和搭配_embarrass是什么意思_embarrass怎么读_embarrass翻译_用法_发音_词组_同反义词_(使)窘迫_(使)局促不安-新东方在线英语词典...
  2. 【问题解决】MISCONF Redis is configured to save RDB snapshots, but it is currently not a
  3. vue+canvas绘制时间轴
  4. 滤镜有什么作用?滤镜这样添加
  5. 微信小程序授权保存图片到相册
  6. 基于c的c++学习day1
  7. LINE登录手机后怎样更换别个账号_新手机如何导入旧手机电话号码
  8. 【问题解决】Vmware虚拟机蓝屏解决方法看这里
  9. 笔记本电脑开机卡住无法正常启动怎么办?
  10. easyui combotree 使用