Docker 学习笔记

学习笔记源自于:https://yeasy.gitbook.io/docker_practice/image/list

什么是 Docker

Docker 是利用 go 写的轻量化容器,Docker 通过 cgroup 等命令来实现进程级别的隔离,与虚拟机相比容器启动速度更快更加灵活不过隔离效果远远不如 VM

镜像

在使用 Docker 的时候我们只需要运行 Docker run 就能快速启动容器来进行应用

镜像主要是提供 Docker 中运行应用所必须的依赖

分层存储

镜像因为有的时候都是操作系统,所以如果不进行分层存储的话就会造成过多镜像的堆积在本地越来越大,所以为了减少镜像占用的体积,采取了分层存储的概念。也就是说如果该镜像中的一些基础或者底层是原来就有的那么就不会下载一个已有的镜像了

容器

镜像与容器的关系就相当于在 Java 中的类和实例,类就是静态,实例就是运行中的实例是动态的

所以与之相对的 镜像就是静态的,容器是镜像运行时的实体。创建之后的容器可以创建、暂停、终止。

容器实质就是进程,只不过通过一些配置拥有自己的根目录、自己的网络配置、自己的资源 。

镜像使用是分层的,所以镜像就是基础层,容器在镜像的基础上进行运行,所以运行之后的数据都是存储在存储层,但是存储层会随着容器消失而消失 ,所以 Docker 建议我们运行中的数据都要存储在数据卷中或者是与宿主机相绑定的目录上

数据卷的生存周期独立于容器,容器消亡,数据卷不会消亡。因此,使用数据卷后,容器删除或者重新运行之后,数据却不会丢失

仓库

那么创建好的镜像,总不能放到自己本地把 ,所以就需要有个地方来进行存放 因此 Docker Register 就诞生了

一个 Docker Registry 中可以包含多个 仓库Repository);每个仓库可以包含多个 标签Tag);每个标签对应一个镜像。

通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。

Ubuntu 镜像 为例,ubuntu 是仓库的名字,其内包含有不同的版本标签,如,16.04, 18.04。我们可以通过 ubuntu:16.04,或者 ubuntu:18.04 来具体指定所需哪个版本的镜像。如果忽略了标签,比如 ubuntu,那将视为 ubuntu:latest

仓库名经常以 两段式路径 形式出现,比如 jwilder/nginx-proxy,前者往往意味着 Docker Registry 多用户环境下的用户名,后者则往往是对应的软件名。但这并非绝对,取决于所使用的具体 Docker Registry 的软件或服务。

镜像

使用镜像

由于镜像只是静态使用,所以我们需要来创建容器

docker run -it --rm ubuntu:18.04 bash

-it: -i 代表交互式操作,t代表终端 这里代表终端是 bash
--rm: 容器退出之后就会进行删除 

列出镜像

$ docker image ls
REPOSITORY           TAG                 IMAGE ID            CREATED             SIZE
redis                latest              5f515359c7f8        5 days ago          183 MB
nginx                latest              05a60462f8ba        5 days ago          181 MB
mongo                3.2                 fe9198c04d62        5 days ago          342 MB
<none>               <none>              00285df0df87        5 days ago          342 MB
ubuntu               18.04               329ed837d508        3 days ago          63.3MB
ubuntu               bionic              329ed837d508        3 days ago          63.3MB

镜像体积

$ docker system df

TYPE                TOTAL               ACTIVE              SIZE                RECLAIMABLE
Images              24                  0                   1.992GB             1.992GB (100%)
Containers          1                   0                   62.82MB             62.82MB (100%)
Local Volumes       9                   0                   652.2MB             652.2MB (100%)
Build Cache                                                 0B                  0B

虚悬镜像

$ docker image prune

image-20211201214615281

中间层镜像

由于 docker 镜像都是多层结构,但是一般使用 docker image ls 中所显示的都是顶层的镜像,只有利用 docker image ls -a 才会显示出所有的镜像

同时可以通过过滤来查看一些特定时间轴的,向下面这个可以显示出自动 mongo 之后下载建立的镜像

docker image ls -f since=mongo:3.2

删除镜像

docker image rm xxxx

[慎用] 利用 commit 将容器做成镜像

将容器保存成镜像

通过 docker diff 命令查看前后改动的地方

docker diff NAMES 

image-20211201225302602

docker commit 命令可以将容器中的存储层拉下来保存到镜像中

要知道,当我们运行一个容器的时候(如果不使用卷的话),我们做的任何文件修改都会被记录于容器存储层里。而 Docker 提供了一个 docker commit 命令,可以将容器的存储层保存下来成为镜像。换句话说,就是在原有镜像的基础上,再叠加上容器的存储层,并构成新的镜像。以后我们运行这个新镜像的时候,就会拥有原有容器最后的文件变化

docker commit 语法

docker commit [选项] <容器ID或容器名> [<仓库名>[:<标签>]]

例:

docker commit --author "KpLi0rn" --message "修改了默认网页" webserver nginx:v2

image-20211201225726338

通过 Docker history 来查看历史改动

image-20211201225910412

来运行之前保存好的镜像

docker run --name "MyServer" -d -p 8891:80 nginx:v2

这种方式虽然做起来非常的方便但是会造成我们打包的镜像会加进来很多臃肿的依赖,除了我们自己别人都不知道这个镜像中到底是哪些命令,可以看到我们执行了操作之后这里的 CREATED BY 并不是确切的命令,所以是未知的,同时这里我们只是修改了一个 index.html 但是可以看出来我们这里的 SIZE 变化也是比较大的

image-20211201230436422

所以我们在打包镜像的时候需要利用 Dockerfile 来进行打包

利用 Dockerfile 来定制镜像

Docker 提供了很多基础类库,可以直接通过 FROM 来拖取基础镜像

然后利用 RUN 命令来进行命令的执行

FROM nginx
RUN echo '<h1>This is My First DockerFile</h1>' > /usr/share/nginx/html/index.html

ps:空白镜像 scratch 有的时候可以不以任何系统为基础,所以我们的指令就会作为镜像的第一层,这样有一个好处就是可以减少镜像的体积

创建镜像,在当前 dockerfile 的位置来进行镜像的创建

docker build -t nginx:v3 .

image-20211201231701142

还有一个需要介绍的就是, RUN 作为 dockerfile 中最常用的命令在使用的时候是需要注意的

在 dockerfile 中每一条命令就是一层 所以下面这个安装 redis 的过程就需要 7 层,但是这样的话会导致镜像变的非常的臃肿,因为对于用户来说 redis 安装只需要一层就好了

FROM debian:stretch

RUN apt-get update
RUN apt-get install -y gcc libc6-dev make wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN mkdir -p /usr/src/redis
RUN tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1
RUN make -C /usr/src/redis
RUN make -C /usr/src/redis install

所以我们只需要利用 && 就可以了

FROM debian:stretch

RUN set -x; buildDeps='gcc libc6-dev make wget' \
    && apt-get update \
    && apt-get install -y $buildDeps \
    && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
    && mkdir -p /usr/src/redis \
    && tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
    && make -C /usr/src/redis \
    && make -C /usr/src/redis install \
    && rm -rf /var/lib/apt/lists/* \
    && rm redis.tar.gz \
    && rm -r /usr/src/redis \
    && apt-get purge -y --auto-remove $buildDeps

镜像构建上下文

回看上面的命令

docker build -t nginx:v3 .

之前我一直以为 . 是当前的 dockerfile 地址,其实不是的在docker中这个打包其实是在服务端的 docker 引擎中进行打包的 ,这里的 . 其实就是相对路径,docker 在执行build 的命令的时候会把当前的内容都打包传到远程的 server 上(利用 rest api 来进行)所以传上去了之后 . 就相当于是相对路径 ,如果遇到 copy 等命令的时候就能将资源进行正确的添加

所以我们在执行一些 copy 命令的时候需要利用相对路径,或者就是根据我们的上下文路径来进行添加

理解构建上下文对于镜像构建是很重要的,避免犯一些不应该的错误。比如有些初学者在发现 COPY /opt/xxxx /app 不工作后,于是干脆将 Dockerfile 放到了硬盘根目录去构建,结果发现 docker build 执行后,在发送一个几十 GB 的东西,极为缓慢而且很容易构建失败。那是因为这种做法是在让 docker build 打包整个硬盘,这显然是使用错误。

一般来说,应该会将 Dockerfile 置于一个空目录下,或者项目根目录下。如果该目录下没有所需文件,那么应该把所需文件复制一份过来。如果目录下有些东西确实不希望构建时传给 Docker 引擎,那么可以用 .gitignore 一样的语法写一个 .dockerignore,该文件是用于剔除不需要作为上下文传递给 Docker 引擎的。

那么为什么会有人误以为 . 是指定 Dockerfile 所在目录呢?这是因为在默认情况下,如果不额外指定 Dockerfile 的话,会将上下文目录下的名为 Dockerfile 的文件作为 Dockerfile。

这只是默认行为,实际上 Dockerfile 的文件名并不要求必须为 Dockerfile,而且并不要求必须位于上下文目录中,比如可以用 -f ../Dockerfile.php 参数指定某个文件作为 Dockerfile

当然,一般大家习惯性的会使用默认的文件名 Dockerfile,以及会将其置于镜像构建上下文目录中。

还可以利用远程 git 来进行创建

```dockerfile
$ docker build -t hello-world https://github.com/docker-library/hello-world.git
Step 1/3 : FROM scratch
 --->
Step 2/3 : COPY hello /
 ---> ac779757d46e
Step 3/3 : CMD ["/hello"]
 ---> Running in d2a513a760ed
Removing intermediate container d2a513a760ed
 ---> 038ad4142d2b
Successfully built 038ad4142d2b

### 操作容器

docker 查看容器全部命令,不进行省略

docker ps -a --no-trunc

![image-20211215215445654](https://cdn.wjlshare.com/image-20211215215445654.png)

#### 守护态运行 

-d:就是 Docker 容器在后台运行

举个例子:docker run -d --name yarn -p 8042:8042 -p 8032:8032 kpli0rn/hadoop-rpc-vuln:3.3.0

可通过 docker container logs [container ID] 来查看控制台的日志情况

#### 进入容器内部 

docker exec -it 69d137adef /bin/bash

#### 容器导入&导出

https://segmentfault.com/a/1190000040340427 导入导出的文章

##### 导出 

docker export [container id] > demo.tar


![image-20211215213847156](https://cdn.wjlshare.com/image-20211215213847156.png)

导出来的就是一个基本的 linux 小目录 

![image-20211215213936295](https://cdn.wjlshare.com/image-20211215213936295.png)

##### 导入

cat /Users/kpli0rn/Desktop/fastjson.tar | docker import - test/fastjson:v1.0


其实直接 import 就行了 docker import fastjson.tar

![image-20211215214139310](https://cdn.wjlshare.com/image-20211215214139310.png)

导入之后变成了 docker iamge

![image-20211215214245110](https://cdn.wjlshare.com/image-20211215214245110.png)

想要运行镜像必须要在运行的最后加上 command

```dockerfile
docker run -d -p 8090:8090 test/fastjson java -Dserver.address=0.0.0.0 -Dserver.port=8090 -jar /usr/src/fastjsondemo.jar

这样就运行成功了

image-20211215215811227

清除

删掉所有终止的容器

docker container prune

访问仓库

把镜像上传到 dockerhub 上的时候

// 先用 docker tag 打个 tag
docker tag ubuntu:18.04 username/ubuntu:18.04

// 然后再push上去
docker push username/ubuntu:18.04

未完待续.....

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇