Docker基础

一、Docker的介绍

1.1 简介

Docker 是基于Go开发的开源应用容器引擎,让开发者可以打包应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux或Windows 等机器上,也可以实现虚拟化。

1.2 解决的问题

  1. 环境不一致
  2. 多用户的操作系统下相互影响
  3. 运维成本高
  4. 安装软件成本过高

1.3 Docker的优势

资源利用率高

容器里的应用就是底层系统的一个进程,而不是一个操作系统,自然对系统资源的利用率更高。

启动快

容器里的应用直接运行于宿主内核,启动容器相当于启动本机的一个进程,无需启动完整的操作系统,因此可以做到秒级、甚至毫秒级的启动时间。极大的节约了开发、测试、部署的时间。

一致的运行环境

开发过程中一个常见的问题是环境一致性问题。由于开发、测试、生产环境不一致,导致有些 bug 并未在开发过程中被发现。而 Docker 的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现 「这段代码在我机器上没问题啊」 这类问题。

持续交付和部署

使用 Docker 可以通过定制应用镜像来实现持续集成、持续交付、部署。开发人员可以通过Dockerfile来进行镜像构建,并结合持续集成进行集成测试,而运维则可以直接在生产环境中快速部署该镜像,甚至结合持续部署系统进行自动部署。

提供弹性的云服务

Docker 容器可以随开随关,很适合动态扩容和缩容。

组建微服务架构

通过多个容器,一台机器可以跑多个服务,因此在本机就可以模拟出微服务架构。

1.4 Docker 的思想

  1. 镜像 (Image)

    Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。

  2. 容器(container)

    容器可以理解成是镜像的实例。镜像是静态的,容器是镜像运行时的实体,可以被创建、启动、暂停、删除等。

    容器的实质是进程,但与直接在宿主执行的进程不同,容器内的进程运行在一个隔离的环境里,拥有自己的 root 文件系统、自己的网络配置、自己的进程空间,甚至自己的用户 ID 空间。

  3. 仓库(Repository)

    镜像构建完成要管理、共享,就需要一个集中存储、分发镜像的服务。Docker Registry 就是这样的服务。可以将Docker Registry理解成Github。一个 Docker Registry 中可以包含多个仓库(Repository);每个仓库可以包含多个 标签Tag);每个标签对应一个镜像。

二、安装Docker

以下操作以mac OS为例。windows也很简单,下载docker安装包,安装,启动即可。

2.1 安装 Homebrew

如果没有安装Homebrew,执行下面命令进行安装:

$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"

Homebrew 是 macOS 或 Linux缺失的软件包管理器。可以安装Apple(或您的 Linux 系统)没有预装但 你需要的东西

Homebrew Cask 扩展了 Homebrew,可以优雅、简单和快速的安装 mac OS 的 GUI 应用程序。

2.2 安装Docker

2.2.1 brew cask 安装

$ brew cask install docker
image-20201123111329442.png

检查是否安装成功:

$ docker --version
$ Docker version 19.03.13, build 4484c46d9d
$ docker-compose --version
$ docker-compose version 1.27.4, build 40524192
$ docker info   

如果都执行正常执行的话说明安装成功。

2.2.2 手动下载安装

下载地址

2.3 镜像加速

国内从 Docker Hub 拉取镜像有时会遇到困难,此时可以配置镜像加速器。国内很多云服务商都提供了加速器服务,例如:

阿里云加速器(点击管理控制台 -> 登录账号(淘宝账号) -> 右侧镜像中心 -> 镜像加速器 -> 复制地址)

网易云加速器 https://hub-mirror.c.163.com

百度云加速器 https://mirror.baidubce.com

我使用的是网易云和百度云,因为无需登录认证就可以下载使用。

2.3.1配置

打开Docker应用,点击设置按钮,点击左侧的Docker Engine,编辑 json 文件(如下)。修改完成之后,点击 Apply & Restart 按钮,Docker 就会重启并应用配置的镜像地址了。

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

验证配置是否生效:

$ docker info

信息中看到如下说明配置成功了

Registry Mirrors:
  https://hub-mirror.c.163.com/
  https://mirror.baidubce.com/

三、操作镜像

3.1 基本指令

获取镜像

$ docker image pull [选项] 仓库名[:标签]

例:

$ docker image pull library/hello-world
  1. docker image pull 是拉取镜像的命令
  2. 选项:具体可通过docker pull --help 查看,包括 -a-q
  3. library/hello-world是image文件在仓库里面的位置,library是 Image 文件所在的组,hello-world是 Image文件的名字。Docker 官方提供的 Image 文件,都放在library组里面,是默认组,所以可以省略library。
  4. 标签:镜像版本号 默认latest

以上可以简写成:

$ docker image pull hello-world

查看镜像

查看本机所有镜像:

$ docker iamge ls

删除镜像

$ docker image rm [OPTIONS] IMAGE [IMAGE...]
  1. docker image rm 删除一个或多个镜像
  2. OPTIONS
    1. --force, -f 强制删除
    2. --no-prune 不删除未标记的父项
  3. IMAGE:可以是镜像名、镜像ID、镜像摘要

四、操作容器

4.1 新建并启动

$ docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
# 或
$ docker container run [OPTIONS] IMAGE

注意:docker run 命令具有自动抓取 Image 文件的功能。如果发现本地没有指定的 Image 文件,就会从远程仓库自动抓取。所以docker image pull命令并非必须。

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

  1. 检查本地是否存在指定的镜像,不存在就从公有仓库下载
  2. 利用镜像创建并启动一个容器
  3. 分配一个文件系统,并在只读的镜像层外面挂载一层可读写层
  4. 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去
  5. 从地址池配置一个 ip 地址给容器
  6. 执行用户指定的应用程序
  7. 执行完毕后容器被终止

基于hello-world镜像创建一个容器:

$ docker run hello-world
image-20201124201844598.png

以上信息输出后,容器就会自动终止。

有些容器不能终止,因为是提供的服务或需要交互。

比如需要进入node环境并执行任务:

$ docker run -it --rm node bash
  1. -it

    这是两个参数, -i:交互式操作, -t是 终端。这里打算进入 bash 执行一些命令并查看返回结果,因此我们需要交互式终端。

image-20201124203207822.png

以上可以看出已经创建了容器并可以在shell下操作,比如进入Node环境,执行操作,比如定义常量a并打印a

image-20201124203448958.png
  1. --rm

    这个参数是说容器退出后随之将其删除。默认情况下,为了排障需求,退出的容器并不会立即删除,除非手动 docker container rm。我们这里只是随便测试一下命令看看结果,不需要排障和保留结果,因此使用 --rm 可以避免浪费空间。

  2. bash

    这里我们希望有个交互式 Shell,因此用的是 bash

对于交互式容器,需要使用exitCtrl+d 指令退出。

image-20201124203801973.png

4.2. 查看本机容器

4.2.1 本机正在运行的容器

$ docker container ls

4.2.2 本机所有容器,包括停止运行的

$ docker container ls --all | -a

本机所有容器:刚才终止运行的hello-world 和 node

image-20201124205619403.png

4.3 终止运行的容器

4.3.1 docker container kill

$ docker container kill [CONTAINER ID]
image-20201124211536262.png

4.3.2 docker container stop

$ docker container stop [CONTAINER ID]
image-20201125104433897.png

4.4 重启已终止的容器

$ docker container start 1aaf8fd9dfd4
image-20201124210213934.png

4.5 删除容器

4.5.1 删除处于终止状态的容器

删除一个处于终于状态的容器:

$ docker container rm [CONTAINER ID]

比如,删除node容器:

$ docker container rm 520606897c06
image-20201124205816745.png

就剩一个hello-world容器了。

4.5.2 删除运行中的容器

如果要删除一个处于运行中的容器,可以添加 -f 参数。Docker 会发送 SIGKILL 信号给容器。

$ docker container rm -f [CONTAINER ID]

4.5.3 清理所有处于终止状态的容器

$ docker container prune

4.6 导入导出

4.6.1 导出容器

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

比如导出 hello-world 容器

$ docker export 14c34720f4f1 > hello-world.tar
image-20201125152403018.png

这样将导出容器快照到本地文件:

image-20201125152458314.png

4.6.2 导入容器快照

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

$ cat hello-rorld.tar | docker import - test/hello-world:1.0
image-20201125153603782.png

五、Dockerfile 定制镜像

定制镜像需要Dockerfile 文本文件,其内包含了一系列指令

1. 新建一个Node项目 my_http

image-20201124192750042.png

2. 创建 .dockerignore

$ touch .dockerignore

3. 编辑 .dockerignore

.dockerignore
.git
.gitignore
node_modules

4. 创建Dockerfile文件

$ cd my_http
$ touch Dockerfile

5. 编辑Dockerfile

FROM node:12.16.0
COPY . /app
WORKDIR /app
RUN npm install
EXPOSE 3000
  1. FROM 指定基础镜像

    所谓定制镜像,那一定是以一个镜像为基础,在其上进行定制。而 FROM 就是指定 基础镜像,因此一个 DockerfileFROM 是必备的指令,并且必须是第一条指令。

    除了选择现有镜像为基础镜像外,Docker 还存在一个特殊的镜像,名为 scratch。这个镜像是虚拟的概念,并不实际存在,它表示一个空白的镜像。

    FROM scratch
    ...
    
  2. COPY . /app

    将当前目录下的所有文件(除了.dockerignore排除的文件),都拷贝进入 image 文件的/app目录

  3. WORKDIR /app

    指定接下来的工作路径为/app

  4. RUN npm install

    /app目录下,运行npm install命令安装依赖。注意,安装后所有的依赖,都将打包进入 image 文件。

  5. EXPOSE 3000

    将容器 3000 端口暴露出来, 允许外部连接这个端口

6. 构建镜像

$ docker image build [OPTIONS] PATH | URL | -

在项目根目录下执行:

$ docker image build -t my_image:1.0 .
  1. docker image build 构建镜像
  2. -t 指定 Image 文件的名字,后面可以用冒号指定标签。如果不指定,默认的标签就是latest
  3. . 点表示 Dockerfile 的上下文路径
image-20201125112844028.png

7. 检查是否构建成功

$ docker image ls
image-20201125112903301.png

8. 创建容器

$ docker container run -p 8000:3000 -it my_image:1.0 bash
  1. -p参数

    容器的 3000 端口映射到本机的 8000 端口

  2. -it

    参数 容器的 Shell 映射到当前的 Shell,然后你在本机窗口输入的命令,就会传入容器

  3. my_image

    image 文件的名字(如果有标签,还需要提供标签,默认是 latest 标签)。

  4. bash

    容器启动以后,内部第一个执行的命令。这里是启动 bash,保证用户可以使用 Shell

image-20201125112811134.png

9. 运行项目

创建容器之后,进入app目录下,并打开shell,执行ls 可以查看当前容器下的文件,接下来执行node index.js,在浏览器访问localhost:8000

image-20201125113229006.png
image-20201125113707315.png

9. CMD命令

以上案例,容器启动以后,需要手动输入命令node index.js。我们可以把这个命令写在 Dockerfile 里面,这样容器启动以后,这个命令就已经执行了,不用再手动输入了。

FROM node:12.16.0
COPY . /app
WORKDIR /app
RUN npm install
EXPOSE 3000
CMD node index.js

注意:指定了CMD命令以后,docker run命令就不能附加命令了(比如bash),否则会覆盖CMD命令。

启动容器:

$ docker run -it --rm -p 8000:3000 my_http_image:1.1
image-20201125143954911.png

CMD 和RUN的区别

RUN命令在 Image 文件的构建阶段执行,执行结果都会打包进入 Image 文件;

CMD命令则是在容器启动后执行。另外,一个 Dockerfile 可以包含多个RUN命令,但是只能有一个CMD命令。

六、仓库

6.1 搜索、拉取

1. 搜索镜像

通过 docker search 命令来查找官方仓库中的镜像,并利用 docker pull 命令来将它下载到本地。

docker search 必须要加一个关键词,如:

$ docker search nginx
image-20201125155017661.png

返回了很多包含关键字的镜像,其中包括镜像名字、描述、收藏数、是否官方创建(OFFICIAL)、是否自动构建 (AUTOMATED)。

根据是否是官方提供,可将镜像分为两类。

一种是类似nginx这样的镜像,被称为基础镜像或根镜像。这些基础镜像由 Docker 公司创建、验证、支持、提供。这样的镜像往往使用单个单词作为名字。

还有一种类型,比如 bitnami/nginx 镜像,它是由 Docker Hub 的注册用户创建并维护的,往往带有用户名称前缀。可以通过前缀 username/ 来指定使用某个用户提供的镜像。

另外,在查找的时候通过 --filter=stars=N 参数可以指定仅显示收藏数量为 N 以上的镜像。

2. 拉取镜像

$ docker pull

6.2 Docker Hub

Docker 官方维护了一个公共仓库 Docker Hub,大部分需求都可以通过在 Docker Hub 中直接下载镜像来实现。

1. 注册

可以在 https://hub.docker.com 免费注册一个 Docker 账号。

2. 登陆

通过执行 docker login 命令交互式的输入用户名及密码来完成在命令行界面登录 Docker Hub。

通过 docker logout 退出登录。

3. 推送

首先为本地的 image 标注用户名和版本

$ docker image tag [imageName] [username]/[repository]:[tag]
# 例:
$ docker image tag my_http_image:1.0 cuilldocker/my_http_image:1.0

也可以不标注用户名,重新构建一下 image 文件。

$ docker image build -t [username]/[repository]:[tag] .
# 例:
$ docker image build -t cuilldocker/my_http_image:1.0 .

最后推送:

$ docker image push [username]/[repository]:[tag]
# 例:
$ docker image push cuilldocker/my_http_image:1.0

至此,关于Dokcer的基本操作/基础暂告一段,以后抽时间会学习怎么用Docker搭建私有仓库、网站、CI/CD。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容