Docker你需要知道的知识点--数据卷、保持镜像、Dockerfile

785 阅读7分钟

目前随着CICD的普及,Docker 的应用也越来越多,为了开发环境和部署环境的统一,公司也开始要求前端在Docker基础上进行项目开发,于是乎最近也开始研究Docker, 这里把学习的docker知识分享下,希望我分享的内容能够帮大家对Docker有个更好的理解,让我们一起学习交流,一起加油!

Docker 数据卷

Docker中数据卷有以下3种方式

  • Volume:挂载宿主文件目录到容器内部, 由docker帮我们创建数据集在宿主中的保持位置,默认位于 /var/lib/docker/volumes目录中 (最常见)
  • Bind Mount: 挂载宿主文件目录到容器内部,可以由用户指定挂载目录到宿主文件系统中的位置,内外的修改都可见(比较常见)
  • Tmpfs Mount: 挂载宿主的内存的一步,但是不是持续化存储,容器停止后会消失(比较少用)

挂载文件到容器

Bind绑定:

## -v <host-path>:<container-path> 或 --volume <host-path>:<container-path> 的方式来自定义绑定容器的路径
docker run -d --name nginxApp -v /nginxTest/html:/usr/share/nginx/html nginx:1.12

## 只读属性“ro”添加之后容器只能读取不能修改
docker run -d --name nginxApp -v /nginxTest/html:/usr/share/nginx/html:ro nginx:1.12

Bind的这种方式因为自定义了路径所有复用性不高,但是遇到下列的两种场景还是可以使用:

  1. 容器中需要引入系统中的一些配置信息
  2. 需要在宿主中修改容器内部的一些配置

Tmpfs绑定

## 使用--tmpfs 
docker run -d --name nginxApp --tmpfs /nginxTest/cache nginx:latest

Tmpfs这种方式一般都使用在保存需要频繁操作IO的数据,或者是一些涉密的敏感数据

Volumes 绑定

## 直接使用 -v ,docker会自动生成一个数据卷来存储nginxApp中的数据卷
docker run -d --name nginxApp -v /nginx/html nginx:latest

## docker volume create 创建一个数据卷
docker volume create nginxData

##  绑定数据到指定的数据卷容器中  -v <name>:<container-path>
docker run -d --name  -v nginxdata:/nginx/html nginx:latest

## 给多个容器共享一个数据卷容器, 一下就是容器nginxTest和 mysqlTest共享容器nginxdata
docker run -d --name nginxTest -v nginxdata:/nginx/html nginx:latest
docker run -d --name mysqlTest -v nginxdata:/data mysql:latest

Volumes这种方式更易于复用,常常在docker-compose 中被使用

数据卷容器的创建

## docker volume create 创建一个数据卷
docker volume create nginx-vol

## docker volume ls 查看所有容器卷
docker volume ls 

## docker volume inspect 查看指定容器卷详情信息
docker volume inspect nginx-vol 

## 删除数据卷容器
docker volume rm nginx-vol 

## 删除容器同时删除管理的数据卷容器
docker rm -v webapp 

## 删除没有被容器关联的 数据卷
docker volume prune -f

数据卷的迁移

  • 打包 backup.tar

    ## 打包/webapp/storage 到 外挂的backup路径 先建立路径对应宿主backup, 然后在容器里面打包 到容器内部backup中,因为是相连的所有宿主机上也有了这个backup.tar
    docker run --rm --volumes-from nginxApp -v $(pwd)/backup:/backup nginx tar cvf /backup/backup.tar /nginx/html
    
  • 解压 backup.tar

    ## 解压bakup.tar 到 容器 webapp/strage 路径
    docker run --rm --volumes-from appdata -v /backup:/backup ubuntu tar cvf /backup/backup.tar /webapp/storage
    
  • 配置 采用csv的方式配置

    docker run -d --name webapp webapp:latest --mount 'type=volume,src=appdata,dst=/webapp/storage,volume-driver=local,volume-opt=type=nfs,volume-opt=device=<nfs-server>:<nfs-path>' webapp:latest
    

保存和共享镜像

提交容器修改

  • 将容器保存为镜像

    ## docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
    ## 提交 容器c3f279d17e0a 为 nginxAppImg 镜像
    docker commit c3f279d17e0a  nginxAppImg
    
    ## 添加保存为镜像的信息
    docker commit -m "test " c3f279d17e0a  nginxAppImg
    
    

镜像迁移

  • 导出镜像

    ## 以数据流的方式导出
    docker save nginxAppImg > nginxAppImg.tar
    
    ## 以文件的方式导出 --output/-o 
    docker save -o ./nginxAppImg.tar nginxAppImg
    
    ## 导出镜像并且使用gzip打包
    docker save nginxAppImg | gzip > nginxAppImg.tar.gz
    
    
  • 导入镜像

    ## 文件流的方式导入 <
    docker load < nginxAppImg.tar.gz
    
    ## 导入TAR压缩文件(支持批量导入) --input , -i
    docker load -i fedora.tar
    
  • 批量操作

    ##批量导出
    docker save -o ./images.tar webapp:1.0 nginx:1.12 mysql:5.7
    
    ##批量导入
    ocker load -i ./images.tar 
    
  • 导出导入容器

    ## 导出容器 --output , -o
    docker export -o ./nginxContainer.tar nginxContainer
    
    ## 导出容器STDOUT流 >
    docker export nginxContainer > nginxContainer.tar
    
    ## 导入容器包生成镜像
    docker import ./nginxContainer.tar
    
    ## 导入远程的包
    docker import https://example.com/exampleimage.tgz
    

通过 Dockerfile 创建镜像

关于Dockerfile

  • Docker 可以通过读取Dockerfile文件来自动构建镜像。Dockerfile是一个文本的文件包含了用户使用的命令行。通过使用docker build来自动创建镜像同时再执行一系列的命令

使用

 ## 使用docker build . 来启动当前路径的 DockerFile
 docker build .
 
 ## 使用-f 来指定DockerFile 的路径
 docker build -f /path/to/a/Dockerfile .
 
 ## 指定一个仓库或者是tag来保持通过Dockerfile构建好的镜像
 docker build -t shykes/myapp .
 
 ## 指定多个仓库或者是tag来保持通过Dockerfile构建好的镜像
 docker build -t shykes/myapp:1.0.2 -t shykes/myapp:latest .
 
 

格式

 # 虽然Dockerfile里面对大小写不敏感,但是为了区别参数更容易一般都采用: 指令(大写)参数(小写的方式) 
 
 # Comment 注释 # 为注释的开头
 INSTRUCTION arguments

转义符

## 在windows 环境下需要使用添加转义符, 在Dockerfile文件顶部

# escape=`
FROM microsoft/nanoserver
COPY testfile.txt c:\
RUN dir c:\

环境变量的替换

## 使用${FOO}  或者 $FOO 作为占位符
## 前面添加\可以取消占位符 \$FOO

FROM busybox
ENV FOO=/bar
WORKDIR ${FOO}   # WORKDIR /bar
ADD . $FOO       # ADD . /bar
COPY \$FOO /quux # COPY $FOO /quux

## 可以使用环境变量的指令
ADD
COPY
ENV
EXPOSE
FROM
LABEL
STOPSIGNAL
USER
VOLUME
WORKDIR
ONBUILD

.dockerignore file

## dockerignore 文件可以指定不打包的问题

*/temp* 路径中包含的temp 例如 /somedir/temp
*/*/temp* 子路径中包含了 temp 例如 /somedir/subdir/temporary.txt
temp? 包含了temp的路径 例如:/tempa 或者 /tempb
!README.md 所有文件 除了README.md

FROM

## FROM 后面添加基础的镜像, ARG 提供参数可以优先于FROM 

ARG  CODE_VERSION=latest
FROM base:${CODE_VERSION}
CMD  /code/run-app

FROM extras:${CODE_VERSION}
CMD  /code/run-extras


## ARG 在FROM 以前的智能在FROM 中使用, 如果需要在FROM 以后的指令使用则可以再次声明
ARG VERSION=latest
FROM busybox:$VERSION
ARG VERSION
RUN echo $VERSION > image_version

RUN

## RUN 用于指定 docker build 过程中要运行的命令。

## 第一种形式
RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME'

## 第二种形式
RUN ["/bin/bash", "-c", "echo hello"]

CMD

## CMD 指令的首要目的在于为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束,和RUN 不同时是 RUN 再docker BUILD时候运行,CMD 在docker run的时候进行 

## CMD3种形式
CMD ["executable","param1","param2"] (exec form, this is the preferred form)
CMD ["param1","param2"] (as default parameters to ENTRYPOINT)
CMD command param1 param2 (shell form)


## 如果使用的是shell格式的,指令会在/bin/sh -c: 中运行
FROM ubuntu
CMD echo "This is a test." | wc -


## 如果使用的不是shell格式的,那么你需要指定命令的绝对路径
FROM ubuntu
CMD ["/usr/bin/wc","--help"]

LABEL

## 为镜像添加元数据 格式: key:value :

## LABEL <key>=<value> <key>=<value> <key>=<value> ...
LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates \
that label-values can span multiple lines."

EXPOSE

## 暴露端口
EXPOSE 8080
EXPOSE 22
EXPOSE 8009
EXPOSE 8005

## 但是注意这里的暴露端口不是真的暴露端口需要在运行的是加-P 才能暴露所有的端口
docker run -d -it -P --name port_list_container port_list

## 使用-p 覆盖EXPOSE
docker run -p 80:80/tcp -p 80:80/udp

ENV

## ENV指令用以定义镜像的环境变量

ENV MY_NAME="John Doe"
ENV MY_DOG=Rex\ The\ Dog
ENV MY_CAT=fluffy

ADD

## ADD指令的功能是将主机构建环境(上下文)目录中的文件和目录、以及一个URL标记的文件 拷贝到镜像中
## 格式
ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]

## 样例
FROM ubuntu
MAINTAINER hello
ADD test1.txt test1.txt
ADD test1.txt test1.txt.bak
ADD test1.txt /mydir/
ADD data1  data1
ADD data2  data2
ADD zip.tar /myzip

COPY

## 本地的文件拷贝到容器镜像中
## 格式
COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]

## 样例
COPY check* /testdir/           # 拷贝所有 check 开头的文件
COPY check?.log /testdir/       # ? 是单个字符的占位符,比如匹配文件 check1.log

## 当COPY和ADD的不同地方
copy 支持 multistage,ADD不支持
ADD 支持URL和解压文件,COPY不支持

ENTRYPOINT

## 支持2种格式
### exec form
ENTRYPOINT ["executable", "param1", "param2"]

###  shell form
ENTRYPOINT command param1 param2

## ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数。但是当指定了 ENTRYPOINT 后, CMD 的含义就发生了改变,不再是直接的运行其命令,而是将 CMD 的内容作为参数传给 ENTRYPOINT 指令

## 例如 
FROM ubuntu:16.04
RUN apt-get update \
    && apt-get install -y curl \
    && rm -rf /var/lib/apt/lists/*
CMD [ "curl", "-s", "http://ip.cn" ]

## 如果执行 docker run myip -i,则 -i 则会替换所有的CMD里面的内容, 但是如果使用 ENTRYPOINT

FROM ubuntu:16.04
RUN apt-get update \
    && apt-get install -y curl \
    && rm -rf /var/lib/apt/lists/*
ENTRYPOINT [ "curl", "-s", "http://ip.cn" ]

## 在运行 docker run myip -i, 则会在后面添加-i 参数,因为容器后面的字段都会替换CMD的内容,而CMD是ENTRYPOINT的参数,所有可以运行 -i


VOLUME

## 指定外挂文件系统,但是这种绑定方式是Volumes的,具体的可以参考我写的第8节的内容
VOLUME ["/data"]

## 样例
FROM ubuntu
RUN mkdir /myvol
RUN echo "hello world" > /myvol/greeting
VOLUME /myvol

USER

## 使用指定用户运行RUN, CMD, ENTRYPOINT的时候
USER <user>[:<group>]
USER <UID>[:<GID>]

## 样例
FROM microsoft/windowsservercore
USER patrick

WORKDIR

## 指定 RUN, CMD, ENTRYPOINT, COPY and ADD 指令的工作目录

### WORKDIR指令可以在Dockerfile中多次使用。如果提供了一个相对路径,它将相对于前面的WORKDIR指令的路径。例如:

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
这个Dockerfile中的最后一个pwd命令的输出是/a/b/c。

### WORKDIR指令可以解析之前使用ENV设置的环境变量。您只能使用在Dockerfile中显式设置的环境变量。例如:

ENV DIRPATH /path
WORKDIR $DIRPATH/$DIRNAME
RUN pwd
这个Dockerfile中的最后一个pwd命令的输出是  /path/$DIRNAME  

### 样例
FROM ubuntu
MAINTAINER hello
RUN mkdir /mydir
RUN echo hello world > /mydir/test.txt
WORKDIR /mydir
CMD ["more" ,"test.txt"]

more 执行的路径就是/mydir

ARG

## ARG 指令定义了一个变量,用户可以在构建时使用 docker build 命令使用--build-arg <varname>=<value> 标志将其传递给构建器。如果用户指定了未在 Dockerfile 中定义的构建参数,则构建会输出警告

## Dockerfile 可能包含一个或多个 ARG 指令。例如,以下是有效的 Dockerfile:
FROM busybox
ARG user1
ARG buildno

## 样例 命令行docker build --build-arg user=what_user . 所以USERS是what_user
FROM busybox
USER ${user:-some_user}
ARG user
USER $user


相关资料

大家喜欢的可以看看我的专栏 (Docker你需要知道的知识点) 我会尽量保持每周更新,如果喜欢的麻烦帮我点个赞,十分感谢

大家如果喜欢“Typescript”的话,可以看看我分享的另外一个专栏(TypeScript常用知识)里面有常见的Typescript知识点分享,希望帮大家更好的理解TS的意义

大家如果喜欢“算法”的话,可以看看我分享的另外一个专栏(前端搞算法)里面有更多关于算法的题目的分享,希望能帮助大家更深的理解算法

文章内容目的在于学习讨论与分享学习TS过程中的心得体会,文中部分素材来源网络,如有侵权,请联系删除,邮箱 182450609@qq.com