Docker容器数据卷 原理:将容器目录挂载到Linux的目录
容器的持久化和同步操作 !容器间也是可以数据共享的
使用数据卷
方式一:直接使用命令来挂载 -v
1 docker run -it -v 主机目录:容器内目录
安装MySQL 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 [root@localhost ~] [root@localhost home] root 13049 12627 0 14:40 pts/5 00:00:00 grep --color=auto mysql [root@localhost home] 95a10c860fd5ab401b7d29f728addff9b99f1f2a6b28286d78d9d78958843a6b [root@localhost home] CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 95a10c860fd5 mysql:5.7 "docker-entrypoint.s…" 6 seconds ago Up 5 seconds 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp kind_shannon [root@localhost home] root@95a10c860fd5:/ Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 2 Server version: 5.7.36 MySQL Community Server (GPL) Copyright (c) 2000, 2021, Oracle and/or its affiliates. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help . Type '\c' to clear the current input statement. mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | +--------------------+ 4 rows in set (0.00 sec) mysql> create database db01; Query OK, 1 row affected (0.00 sec) mysql> use db01 Database changed mysql> create table student(id int,name varchar(20)); Query OK, 0 rows affected (0.01 sec) mysql> insert into student values(1,'z3' ); Query OK, 1 row affected (0.04 sec) mysql> select * from student ; +------+------+ | id | name | +------+------+ | 1 | z3 | +------+------+ 1 row in set (0.00 sec) mysql> select * from student; +------+------+ | id | name | +------+------+ | 1 | z3 | | 2 | lisi | +------+------+ 2 rows in set (0.00 sec) mysql> show variables like 'character%' ; +--------------------------+----------------------------+ | Variable_name | Value | +--------------------------+----------------------------+ | character_set_client | latin1 | | character_set_connection | latin1 | | character_set_database | latin1 | | character_set_filesystem | binary | | character_set_results | latin1 | | character_set_server | latin1 | | character_set_system | utf8 | | character_sets_dir | /usr/share/mysql/charsets/ | +--------------------------+----------------------------+ 8 rows in set (0.01 sec) [root@localhost ~] --privileged=true \ -v /home/mysql/conf:/etc/mysql/conf.d \ -v /home/mysql/data:/var/lib/mysql \ -v /home/mysql/log:/var/log/mysql \ -e MYSQL_ROOT_PASSWORD=123456 \ --name mysql01 mysql:5.7 vi /home/mysql/conf/my.cnf [client] default_character_set=utf8 [mysqld] collation_server = utf8_general_ci character_set_server = uft8 [mysql] default-character-set=utf8mb4 [mysqld] character_set_server = utf8 init_connect='SET NAMES utf8' lower_case_table_names=1 [root@localhost ~] --privileged=true \ -v /home/mysql/conf:/etc/mysql/conf.d \ -v /home/mysql/data:/var/lib/mysql \ -v /home/mysql/log:/var/log/mysql \ -e MYSQL_ROOT_PASSWORD=123456 \ --name mysql01 mysql:5.7 \ --character-set-server=utf8mb4 \ --collation-server=utf8mb4_unicode_ci 新项目只考虑utf8mb4 UTF-8 编码是一种变长的编码机制,可以用1~4个字节存储字符。 因为历史遗留问题,MySQL 中的 utf8 编码并不是真正的 UTF-8,而是阉割版的,最长只有3个字节。当遇到占4个字节的 UTF-8 编码,例如 emoji 字符或者复杂的汉字,也就是我们通常在聊天时发的小黄脸表情,会导致存储异常。 从 5.5.3 开始,MySQL 开始用 utf8mb4 编码来实现完整的 UTF-8,其中 mb4 表示 most bytes 4,最多占用4个字节,用来兼容四个字节的Unicode(万国码)。utf8mb4是utf8的一个扩展。从 8.0 之后,将会在某个版本开始用 utf8mb4 作为默认字符编码。 docker restart mysql02
具名与匿名挂载 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 # 查看卷的命令 # [root@localhost home] Usage: docker volume COMMAND Manage volumes Commands: create Create a volume inspect Display detailed information on one or more volumes ls List volumes prune Remove all unused local volumes rm Remove one or more volumes -v 容器内路径! docker run -d -P # 匿名挂载 [root@localhost home]# docker run -d -P --name nginx01 -v /etc/nginx nginx # 具名挂载 # -v 卷名:容器内路径 [root@localhost home]# docker run -d -P --name nginx02 -v my-nginx:/etc/nginx nginx # 查看挂载路径 [root@localhost home]# docker volume inspect my-nginx [ { "CreatedAt": "2022-06-28T22:46:09-04:00", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/my-nginx/_data", "Name": "my-nginx", "Options": null, "Scope": "local" } ] # 所有的docker容器内的卷,没有自定义目录的情况下都是在/var/lib/docker/volumes/xxx/_data
1 2 3 4 5 6 7 8 9 10 11 # 如何确定是具名挂载还是匿名挂载,还是指定路径挂载! -v 容器内路径 # 匿名挂载 -v 卷名:容器内路径 # 具名挂载 -v /宿主机路径:/容器内路径 # 指定路径挂载 # 通过 -v 容器内路径:ro rw 改变读写权限 ro readonly #只读 rw readwrite #读写 # 一旦这个设置容器权限,容器对我们挂载出来的内容就有先限定了! docker run -d -P --name nginx02 -v my-nginx:/etc/nginx:ro nginx docker run -d -P --name nginx02 -v my-nginx:/etc/nginx:rw nginx
初识Dockerfile Dockerfile 就是用来构建 docker 镜像的构建文件 ! 命令脚本!
通过这个脚本可以生成镜像,镜像是一层一层的,脚本一个个的命令,每个命令都是一层!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 [root@localhost docker-test-volume ] [root@localhost docker-test-volume ] FORM centos VOLUME ["volume01" ,"volume02" ] CMD echo "------end------" CMD /bin/bash [root@localhost docker-test-volume ] -f 指定dockerfile文件 -t 指定镜像名以及版本 . 在当前目录生成 docker run -it --name docker03 --volumes-from docker01 shawn/centos:1.0(镜像启动)
结论:
容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止。
但是一旦你持久化到了本地,这个时候,本地的数据是不会删除的
DockerFile构建过程 基础知识 1、每个保留关键字(指令)都是必须是大写字母
2、执行从上到下顺序执行
3、#表示注释
4、每个指令都会创建提交一个新的镜像层,并提交!
1 2 3 4 5 可写容器(container) 镜像(tomcat) 镜像(jdk) rootfs (基础镜像 centos/ubuntu) bootfs
dockerfile是面向开发的,我们以后要发布项目,做镜像,就需要编写dockerfile文件,这个文件十分简单!
Docker镜像逐渐成为企业交付的标准,必须要掌握 !
步骤:开发 部署 运维 缺一不可 !
DockerFile:构建文件,定义了一切的步骤,源代码
DockerImages:通过DockerFile构建生成镜像,最终发布与运行的产品
Docker容器:容器就是镜像运行起来提供服务的
Dockerfile指令 1 2 3 4 5 6 7 8 9 10 11 12 FROM MAINTAINER RUN ADD WORKDIR VOLUME EXPOSE CMD ENTRYPOINT ONBUILD COPY ENV
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 FROM 功能为指定基础镜像,并且必须是第一条指令。 如果不以任何镜像为基础,那么写法为:FROM scratch。 同时意味着接下来所写的指令将作为镜像的第一层开始 语法: FROM <image>FROM <image>:<tag>FROM <image>:<digest> 三种写法,其中<tag>和<digest> 是可选项,如果没有选择,那么默认值为latest RUN 功能为运行指定的命令 RUN 命令有两种格式 1 . RUN <command > 2 . RUN ["executable" , "param1" , "param2" ] 第一种后边直接跟shell 命令 在linux操作系统上默认 /bin/sh -c 在windows操作系统上默认 cmd /S /C 第二种是类似于函数调用。 可将executable理解成为可执行文件,后面就是两个参数。 两种写法比对: RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME RUN ["/bin/bash", "-c", "echo hello"] 注意:多行命令不要写多个RUN ,原因是Dockerfile中每一个指令都会建立一层. 多少个RUN 就构建了多少层镜像,会造成镜像的臃肿、多层,不仅仅增加了构件部署的时间,还容易出错。 RUN 书写时的换行符是\ CMD 功能为容器启动时要运行的命令 语法有三种写法 1 . CMD ["executable","param1","param2"] 2 . CMD ["param1","param2"] 3 . CMD command param1 param2 第三种比较好理解了,就时shell 这种执行方式和写法 第一种和第二种其实都是可执行文件加上参数的形式 举例说明两种写法: CMD [ "sh", "-c", "echo $HOME" CMD [ "echo", "$HOME" ] 补充细节:这里边包括参数的一定要用双引号,就是",不能是单引号。千万不能写成单引号。 原因是参数传递后,docker解析的是一个JSON array RUN & CMD 不要把RUN和CMD搞混了。 RUN是构件容器时就运行的命令以及提交运行结果 CMD是容器启动时执行的命令,在构件时并不运行,构件时紧紧指定了这个命令到底是个什么样子 LABEL 功能是为镜像指定标签 语法: LABEL <key>=<value> <key>=<value> <key>=<value> ... 一个Dockerfile种可以有多个LABEL,如下: 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." 但是并不建议这样写,最好就写成一行,如太长需要换行的话则使用\符号 如下: LABEL multi.label1="value1" \ multi.label2="value2" \ other="value3" 说明:LABEL 会继承基础镜像种的LABEL,如遇到key相同,则值覆盖 MAINTAINER 指定作者 语法: MAINTAINER <name>EXPOSE 功能为暴漏容器运行时的监听端口给外部 但是EXPOSE 并不会使容器访问主机的端口 如果想使得容器与主机的端口有映射关系,必须在容器启动的时候加上 -P参数 ENV 功能为设置环境变量 语法有两种 1 . ENV <key> <value>2 . ENV <key>=<value> ...两者的区别就是第一种是一次设置一个,第二种是一次设置多个 ADD 一个复制命令,把文件复制到景象中。 如果把虚拟机与容器想象成两台linux服务器的话,那么这个命令就类似于scp,只是scp需要加用户名和密码的权限验证,而ADD 不用。 语法如下: 1 . ADD <src>... <dest> 2 . ADD ["<src>",... "<dest>"] <dest>路径的填写可以是容器内的绝对路径,也可以是相对于工作目录的相对路径 <src>可以是一个本地文件或者是一个本地压缩文件,还可以是一个url 如果把<src>写成一个url,那么ADD 就类似于wget命令 如以下写法都是可以的: ADD test relativeDir/ ADD test /relativeDir ADD http://example.com/foobar / 尽量不要把<scr>写成一个文件夹,如果<src>是一个文件夹了,复制整个目录的内容,包括文件系统元数据 COPY 看这个名字就知道,又是一个复制命令 语法如下: 1 . COPY <src>... <dest> 2 . COPY ["<src>",... "<dest>"] 与ADD 的区别 COPY 的<src>只能是本地文件,其他用法一致 ENTRYPOINT 功能是启动时的默认命令 语法如下: 1 . ENTRYPOINT ["executable", "param1", "param2"] 2 . ENTRYPOINT command param1 param2 如果从上到下看到这里的话,那么你应该对这两种语法很熟悉啦。 第二种就是写shell 第一种就是可执行文件加参数 与CMD 比较说明(这俩命令太像了,而且还可以配合使用): 1 . 相同点:只能写一条,如果写了多条,那么只有最后一条生效 容器启动时才运行,运行时机相同 2 . 不同点: ENTRYPOINT 不会被运行的command覆盖,而CMD则会被覆盖 如果我们在Dockerfile种同时写了ENTRYPOINT 和CMD,并且CMD指令不是一个完整的可执行命令,那么CMD指定的内容将会作为ENTRYPOINT的参数 如下: FROM ubuntuENTRYPOINT ["top", "-b"] CMD ["-c"] 如果我们在Dockerfile种同时写了ENTRYPOINT 和CMD,并且CMD是一个完整的指令,那么它们两个会互相覆盖,谁在最后谁生效 如下: FROM ubuntuENTRYPOINT ["top", "-b"] CMD ls -al 那么将执行ls -al ,top -b不会执行。 Docker官方使用一张表格来展示了ENTRYPOINT 和CMD不同组合的执行情况 (下方表格来自docker官网) VOLUME 可实现挂载功能,可以将内地文件夹或者其他容器种得文件夹挂在到这个容器种 语法为: VOLUME ["/data"] 说明: ["/data" ]可以是一个JsonArray ,也可以是多个值。所以如下几种写法都是正确的 VOLUME ["/var/log/"] VOLUME /var/log VOLUME /var/log /var/db 一般的使用场景为需要持久化存储数据时 容器使用的是AUFS,这种文件系统不能持久化数据,当容器关闭后,所有的更改都会丢失。 所以当数据需要持久化时用这个命令。 USER 设置启动容器的用户,可以是用户名或UID,所以,只有下面的两种写法是正确的 USER daemoUSER UID注意:如果设置了容器以daemon用户去运行,那么RUN , CMD 和 ENTRYPOINT 都会以这个用户去运行 WORKDIR 语法: WORKDIR /path/to/workdir 设置工作目录,对RUN ,CMD,ENTRYPOINT,COPY,ADD生效。如果不存在则会创建,也可以设置多次。 如: WORKDIR /a WORKDIR b WORKDIR c RUN pwd pwd执行的结果是/a/b/c WORKDIR 也可以解析环境变量 如: ENV DIRPATH /pathWORKDIR $DIRPATH/$DIRNAME RUN pwd pwd的执行结果是/path/$DIRNAME ARG 语法: ARG <name>[=<default value>]设置变量命令,ARG 命令定义了一个变量,在docker build创建镜像的时候,使用 --build-arg <varname>=<value>来指定参数 如果用户在build镜像时指定了一个参数没有定义在Dockerfile种,那么将有一个Warning 提示如下: [Warning] One or more build-args [foo] were not consumed. 我们可以定义一个或多个参数,如下: FROM busyboxARG user1ARG buildno... 也可以给参数一个默认值: FROM busyboxARG user1=someuserARG buildno=1 ... 如果我们给了ARG 定义的参数默认值,那么当build镜像时没有指定参数值,将会使用这个默认值 ONBUILD 语法: ONBUILD [INSTRUCTION]这个命令只对当前镜像的子镜像生效。 比如当前镜像为A,在Dockerfile种添加: ONBUILD RUN ls -al 这个 ls -al 命令不会在A镜像构建或启动的时候执行 此时有一个镜像B是基于A镜像构建的,那么这个ls -al 命令会在B镜像构建的时候被执行。 STOPSIGNAL 语法: STOPSIGNAL signalSTOPSIGNAL 命令是的作用是当容器推出时给系统发送什么样的指令HEALTHCHECK 容器健康状况检查命令 语法有两种: 1 . HEALTHCHECK [OPTIONS] CMD command 2 . HEALTHCHECK NONE 第一个的功能是在容器内部运行一个命令来检查容器的健康状况 第二个的功能是在基础镜像中取消健康检查命令 [OPTIONS]的选项支持以下三中选项: --interval=DURATION 两次检查默认的时间间隔为30 秒 --timeout=DURATION 健康检查命令运行超时时长,默认30 秒 --retries=N 当连续失败指定次数后,则容器被认为是不健康的,状态为unhealthy,默认次数是3 注意: HEALTHCHECK 命令只能出现一次,如果出现了多次,只有最后一个生效。 CMD 后边的命令的返回值决定了本次健康检查是否成功,具体的返回值如下: 0 : success - 表示容器是健康的1 : unhealthy - 表示容器已经不能工作了2 : reserved - 保留值例子: HEALTHCHECK --interval=5m --timeout=3s \ CMD curl -f http://localhost/ || exit 1 健康检查命令是:curl -f http://localhost/ || exit 1