Docker 入门

引言

假如我们没有虚拟机,该怎么样让别人运行我们的项目,初学的时候,我们往往是打包代码,发给对方,然后让对方安装相应的环境,比如node、数据库,要是配置不同,项目很有可能无法运行,还会报错,如果多个人想要运行这份代码,那还得多次安装配置环境。

当学习完虚拟机之后,我们可以直接发个链接给别人就可以查看,就得开始部署在服务器上。然后去买了服务器,学了linux,去服务器上搭建环境,下载node、mongogb,安装各种项目启动需要的东西,中途可能还安装不成功,然后XShell上传打包好的代码,然后解压运行,测试是否运行正常,ok,可以链接发给别人看了。

但是总归是有些不方便吧,毕竟安装虚拟机配置环境,运行起来之后还特别吃内存,占用资源直接一半。

直到学习docker之后,发现这些问题突然就可以得到解决了,那接下来让我们看看docker到底是什么,解决了什么样的问题,怎么操作吧


1.环境配置的问题

软件开发的时候,环境配置不同,很可能造成项目无法运行,每次其他人运行都需要配置相应的环境,

从根本上解决问题:软件带环境安装,安装的时候把原始环境一模一样的复制过去

解决方案:

(1)虚拟机

带环境安装的一种解决办法,可以在windows上运行linux系统,通过虚拟机可以还原软件原始环境

优点:

  • 相当于真实系统,但是对于底层又是一个普通文件,可以随时删除,方便删除

缺点:

  • 资源占用多:在物理服务器创建一台虚拟机时,便需要虚拟出一套硬件并在上面运行完整的操作系统

  • 冗余步骤多:必须有完整的操作过程,比如登录

  • 启动慢

(2)Linux容器

Linux 容器(Linux Containers,缩写为 LXC):Linux不是模拟的完整的操作系统,而是对进程进行隔离,在正常进程的外面套了一个保护层形成容器。对于容器里面的进程来说,它接触到的各种资源都是虚拟的,从而实现与底层系统的隔离

优势【相对于虚拟机】:

  • 启动快

  • 用资源少

  • 体积小:只是一个进程,而不是完整的操作系统

类似一个轻量级的虚拟机,但是对比于虚拟机,优点很多,虚拟机和linux都是带环境安装的解决办法,而Docker就是在linux容器的基础上发展的。

2.Docker是什么

Docker 基于Linux 容器的一种封装,提供简单易用的容器使用接口

Docker 将应用程序与该程序的依赖,打包在一个文件里面。运行这个文件,就会生成一个虚拟容器。就不用担心环境问题了,容器还可以进行版本管理、复制修改等。

常常我们会觉得Docker是一个小型的虚拟机,但是其实本质不同,Docker不是在宿主机上虚拟出一套硬件后再虚拟出一个操作系统,而是让 Docker 容器里面的进程直接运行在宿主机上(Docker 会做文件、网络等的隔离),被隔离的进场也就是容器,可以完全独立于宿主机的进程

(1)Docker优点

(1)提供一次性的环境:本地测试他人软件,持续集成的时候提供单元测试和构建的环境

(2)配置简化:将环境和配置放入代码然后部署,同样的Docker配置能够在各种环境中使用

(3)快速部署:适用于持续集成和持续交付(CI/CD)

(2)docker容器和虚拟机的对比

对比 docker容器 虚拟机
启动时间 秒级 分钟级
系统支持量 上千个 一般只能几十个
硬盘占用 KB-MB GB-TB
隔离级别 进程级 操作系统级

3.Docker组成

(1)Docker架构

Docker使用C/S架构

客户端:Docker客户端与 Docker守护进程对话,,比如使用docker run等命令

服务端:负责构建、运行和分发 Docker 容器的繁重工

  • Client:客户端是是Docker用户和Docker交互的方式,比如那些执行命令

  • DOCKER_HOST:用来监听客户端请求命令管理Docker对象

  • Registry:镜像仓库存储Docker镜像,类似代码仓库github,比如Docker Hub (官方的),本文后续使用Harbor(私有的)

    image-20211109145330004.png

(2)Docker对象:

Docker管理的对象包含镜像、容器、网络、数据卷,仅介绍镜像和容器,是在操作中常用的

  • Image(镜像):Docker 把应用程序及其依赖[提供运行项目的时候所需的程序,库,资源,配置等],打包在 image 文件里面。只有通过image,才能生成 Docker 容器。image 文件可以看作是容器的模板。Docker 根据 image 文件生成容器的实例。同一个 image 文件,可以生成多个同时运行的容器实例。

  • Container(容器):容器 = 镜像 (dockerfile每个命令生成一层,但是都是只读层) + 读写层(可读可写的最后一层包含容器),容器可以被创建、启动、停止、删除、暂停等。

4.Docker的使用教程

(1)安装Docker

菜鸟教程中有各个平台安装Docker的方法,本文将在windows上进行安装操作

windows docker安装【win10上安装需要查看电脑属性,需要符合64位的win10专业版,企业版,或者教育版构建在15063或者更高版本】

安装之后报错:Docker. ApiServices. WSL2. WslKernelUpdateNotIns talledException的异常


image-20211018143911623.png

下载wsl路径及办法

检查windows版本之后安装wsl,重启电脑之后报错消失

cmd里面运行docker version或者docker info查看是否安装成功

通常使用cli命令行来操作Docker,就像git一样

// 打印docker版本
docker version

(2)运行Docker测试

创建文件夹 hello-docker,创建index.html文件,随便写点儿什么

再创建Dockerfile文件,复制以内容:

 # 基于哪个镜像
FROM nginx
 # 将宿主机中的./index.html文件复制进容器里的/html/index.html
COPY ./index.html html/index.html
 # 容器对外暴露80端口
EXPOSE 80

然后打包镜像:

cd hello-docker/ // 进入刚刚的目录 以管理员身份打开PowerShell
docker image build ./ -t hello-docker:1.0.0 // 打包镜像 基于路径./(当前路径)打包一个镜像,镜像的名字是hello-docker,版本号是1.0.0。该命令会自动寻找Dockerfile来打包出一个镜像

然后查看本机已有镜像【基础命令可以在cmd里面执行,也可以直接打开安装好的docker desktop 直接查看镜像容器等情况】:

docker images
docker images ls

删除本机已有的镜像:

docker rmi [imageId] // 可删除

运行容器:

docker container create -p 5000:80 hello-docker:1.0.0 // 根据镜像创建一个容器并返回容器id 端口是本机暴露5000端口
docker container start xxx // xxx 为上一条命令运行得到的结果 ## 启动一个创建好的容器

查看容器:

docker container ls//查看正在运行的容器
docker ps //查看正在运行的容器
docker ps -a // 查看所有的容器,包括停止运行的容器

最后访问http://localhost:5000/就可以查看到index.html里面的内容

更多创建容器的命令请查看官方文档https://docs.docker.com/engine/reference/commandline/create/

(3)下拉官方镜像运行

让我们继续进行Docker的使用

我们可以直接使用Docker 的官方仓库里面的东西,比如一个hello world 案例,直接在某个文件夹中进行下面的操作

docker image pull library/hello-world // 将 image 文件从仓库抓取到本地。
docker image ls // 看到所有的image文件
docker container run hello-world // 运行image生成的运行的容器实例
docker container kill [containID] //终止容器 有的是可以自动终止的
docker container rm [containerID] //  删除容器
docker container ls --all //列出本机所有容器,包括终止运行的容器

学习如上操作之后,Docker的基本操作都上手了一遍,从上面的简单例子中知道要image文件之后,需要生成image文件就需要Dockerfile 文件,是一个包含用于组合映像的命令的文本文档,用来配置image的。

下面进行Dockerfile文件内容的编写和学习,学完之后就可以进行自己项目的镜像,提供给其他人使用了。

(4)Dockerfile文件学习

Docker 根据 该文件生成二进制的 image 文件。

  • 基本结构

基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令,’#’ 为 Dockerfile 中的注释

  • 常用文件说明

FROM:指定基础镜像,必须是第一个命令

// FROM <image>:<tag>
// FROM <image>@<digest>
// FROM <image>
FROM mysql:5.6
// tag或digest是可选的,不使用这两个值时,会使用latest版本的基础镜像

MAINTAINER:指定作者

 MAINTAINER <name>
 // MAINTAINER sorex@163.com

RUN:构建镜像时执行的命令

// RUN 《command》

ADD:将本地文件添加到容器中

// ADD 《src》 《destination》
ADD test /absoluteDir/    # 添加 "test" 到 /absoluteDir/

COPY:复制命令 类似ADD

CMD:提供了容器默认的执行命令,构建容器后调用,也就是在容器启动时才进行调用。多个CMD就只会执行最后一个,

CMD echo "This is a test." | wc -
CMD ["/usr/bin/wc","--help"]
// CMD ["executable","param1","param2"] (执行可执行文件,优先)
// CMD ["param1","param2"] (设置了ENTRYPOINT,则直接调用ENTRYPOINT添加参数)
// CMD command param1 param2 (执行shell内部命令)

EXPOSE:指定容器在运行时监听的端口

EXPOSE <port>;
// EXPOSE 80;

ENV:设置环境变量。它们使用键值对,增加运行程序的灵活性

// ENV <key> <value>
ENV LOG_LEVEL=debug
ENV NODE_ENV=production

USER:镜像正在运行时设置一个UID

USER <uid>

WORKDIR:相当于cd 进入文件夹

// WORKDIR path
WORKDIR /usr/local/hello

(5)本地项目操作封装成docker

本地项目使用主要技术如下

1.Vue3.0+ts+element-plus构建前端页面
2.koa+koa-router+ts构建后台服务

新建忽略文件.dockerignore

.git
node_modules
npm-debug.log

由于docker是只能启动一个服务,所以把前后端合在一起,然后打包前端项目

如果是单独的前端项目,则只需要直接进行打包之后新建一个文本文件 Dockerfile,按照上面的Dockerfile进行学习之后编写即可

项目Dockerfile如下

# Build environment 指定基础镜像
FROM node:alpine

# Copy packages 复制本地的代码
COPY . .

# run Monorepo 安装依赖
RUN yarn install

# run project 进入运行目录
WORKDIR packages/back

# 导出端口
EXPOSE 3000

# 运行命令
CMD ["node","dist/index.js"]

运行启动

docker image build ./ -t filedemo:1.0.0
docker container create -p 5000:3000 filedemo:1.0.0 //-p参数:容器的 3000 端口映射到本机的 5000 端口,访问时启动5000端口
docker container start 容器id号

直接访问ip:5000端口即可,现在在本机可以进行项目的自由访问了,但是如果别人需要使用,就需要上传仓库。

5.Harbor镜像上传和下载操作

虽然docker官方提供了公共的镜像仓库,但是出于安全和效率方面的考虑,将镜像上传私有仓库也是非常好的选择,比如Harbor

下面将项目上传私有仓库

(1)Harbor镜像上传

账号登录

// docker login ip地址
docker login 192.168.0.7
// 然后输入账号密码即可
// or
// docker login -u 账号名 -p 密码 仓库地址端口
docker login -u xxx -p xxx 192.168.0.7
// WARNING! Using --password via the CLI is insecure. Use --password-stdin.
// Error response from daemon: Get "https://192.168.0.7/v2/": dial tcp 192.168.0.7:443: connect: connection refused
// 如果登录失败,则是原因是因为仓库没有配置https 的问题
// 去修改docker里面的daemon.json
  "insecure-registries": [
    "192.168.0.7"// 加上远程的仓库地址
  ],
// 然后重启docker

给项目打tag

//查看image
docker images
// docker tag 本地镜像名字:标签名字 仓库tag名字
docker tag filedemo:1.0.1 192.168.0.7/node/fileupload:v1.0.1

上传仓库

docker push 192.168.0.7/node/fileupload:v1.0.1

(2)Harbor镜像下载操作

依旧登录进去

然后拉取镜像,和代码仓库命令类似

docker pull 192.168.0.7/node/fileupload:v1.0.1

拉取后docker images查看是否拉取到本地

直接创建容器并运行

docker container create -p 3002:3000 192.168.0.7/node/fileupload:v1.0.1 # 根据镜像创建一个容器并返回容器id
docker container start 前一步返回的ID # 运行容器

访问localhost:3002即可

(3)portainer基础使用教程

portainer是docker的图形化管理界面,可以把仓库里面的docker放在上面进行管理,就不需要使用命令进行启动这些操作,图形化界面操作会更简单容易。

拉取私有仓库的images

image-20211109164732320.png

创建容器,选择侧边的containers->add container


image-20211109165310926.png

如上所示,就建好了容器管理了私有仓库的镜像,然后就可以根据根据自己设置的端口进行访问,别人也可以直接访问,可以形成和虚拟机一样的效果,但是操作更简单方便。

(4)Docker容器的重启策略

16347858307850.png

Docker容器的重启策略是面向生产环境的启动策略,开发过程中可以忽略。

never,默认策略,在容器退出时不重启容器 on-failure,在容器非正常退出时(退出状态非0),才会重启容器 on-failure:3,在容器非正常退出时重启容器,最多重启3次 always,在容器退出时总是重启容器 unless-stopped,在容器退出时总是重启容器,但是不考虑在Docker守护进程启动时就已经停止了的容器

6.Docker镜像的优化

由于构建镜像之后,发现镜像比较大,可能有几百MB或者有的上TB,那其实应该进行一个优化的,让这些镜像尽量占用少的空间,因为本来容器设计初衷就是为了快速和小巧独立,利于一次构建,多处运行

(1)命令合在一起使用&&等操作符,减少层

docker镜像是分层构建的,Dockerfile每条指令都会新建一层作为只读层,如果你新建容器,就会在最顶部添加读写层,每新增一层都会增加镜像的尺寸,所以可以减少命令的条数,把运行命令合在一起

 RUN cd /home/app && npm install --production

(2)使用小的基础镜像

可以使用Alpine作为基础镜像,一般基础镜像有Ubuntu、CentOs、Debian、Alpine,下面是一般的基础镜像的大小

REPOSITORY  TAG       IMAGE ID             SIZE
centos      7         49f7960eb7e4         200MB
debian      latest    0af60a5c6dd0         101MB
ubuntu      18.04     47b19964fb50         88.1MB
ubuntu      latest    47b19964fb50         88.1MB
alpine      3.8       3f53bb00af94         4.41MB

一看alpine就小得多,可以减少大部分的体积

(3)依赖的话需要打包的只需要安装到生产环境里面

需要的运行时的依赖,放到生产环境中,开发时候的依赖,放到开发环境中,不必要放到生产环境中

(4)善用.dockerignore文件

.dockerignore文件,是用来声明不会被镜像包括的文件和目录。这有助于避免将不必要的大文件或敏感文件打包进去,并避免将它们添加到公共镜像。

7.参考资料

1.《Docker run reference》

2.阮一峰Docker入门教程

3.Linux容器

4.Docker官网

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

推荐阅读更多精彩内容