一起来学Docker(六)

前言

目前正在出一个Docker系列教程, 篇幅会较多, 喜欢的话,给个关注❤️ ~

Docker大家应该都听说过,特别是在当今云原生爆火的时代,更值得我们去学习,下面会带大家系统性的认识一下Docker,并结合一些例子,让大家快速上手~

好了, 废话不多说直接开整吧~

构建镜像

前面几节都是使用的第三方镜像,那如何构建自己的应用镜像呢?在docker中提供了build命令

语法:

shell 复制代码
docker build [OPTIONS] PATH | URL | -

OPTIONS说明:

shell 复制代码
--build-arg=[] :设置镜像创建时的变量;

--cpu-shares :设置 cpu 使用权重;

--cpu-period :限制 CPU CFS周期;

--cpu-quota :限制 CPU CFS配额;

--cpuset-cpus :指定使用的CPU id;

--cpuset-mems :指定使用的内存 id;

--disable-content-trust :忽略校验,默认开启;

-f :指定要使用的Dockerfile路径;

--force-rm :设置镜像过程中删除中间容器;

--isolation :使用容器隔离技术;

--label=[] :设置镜像使用的元数据;

-m :设置内存最大值;

--memory-swap :设置Swap的最大值为内存+swap,"-1"表示不限swap;

--no-cache :创建镜像的过程不使用缓存;

--pull :尝试去更新镜像的新版本;

--quiet, -q :安静模式,成功后只输出镜像 ID;

--rm :设置镜像成功后删除中间容器;

--shm-size :设置/dev/shm的大小,默认值是64M;

--ulimit :Ulimit配置。

--squash :将 Dockerfile 中所有的操作压缩为一层。

--tag, -t: 镜像的名字及标签,通常 name:tag 或者 name 格式;可以在一次构建中为一个镜像设置多个标签。

--network: 默认 default。在构建期间设置RUN指令的网络模式

在大部分情况下,构建本地镜像都依赖Dockerfile文件,通过它可以定义一些属性

如果依赖当前目录下的Dockerfile,我们可以这么写:

shell 复制代码
docker build -t web/web:latest . 

当然也可以指定文件:

shell 复制代码
docker build -f ./docker/Dockerfile -t web/web:latest . 

大部分情况,使用第一种的会比较多,因为一般我们都会将文件放到项目的根目录下,这个可以根据自己的设定进行调整

我们知道了具体的命令后,下面就一起看一下Dockerfile的语法

Dockerfile

首先Dockerfile是一个文件,在它的文件中,我们可以定义诸多命令,你也可以比作是linuxshell脚本,在脚本中定义了一些命令来自动化的执行一些事情。在Dcokerfile中,我们通常称为指令,我们可以通过指令一步步构建自己的应用镜像

所以它有特定的语法,需要注意的是linux中的命令不适用于Dockerfile,这里大家要区分开,下面我们就一起看下有哪些指令吧

FROM

指定父镜像,指定Dockerfile基于那个image构建

MAINTAINER

作者信息,用来标明这个Dockerfile谁写的

LABEL

标签,用来标明Dockerfile的标签,可以使用Label代替Maintainer,最终都是在docker image基本信息中可以查看

RUN

执行命令, 执行一段命令,默认是/bin/sh 格式: RUN command 或者 RUN ["command" , "param1","param2"]

CMD

指定容器创建时的默认命令。

ENTRYPOINT

设置容器创建时的主要命令。(不可被覆盖)比如我们部署服务端的应用,服务的启动命令就写在这

COPY

复制文件, build的时候复制文件到镜像中,比如在制作前端应用的镜像时,我们可以直接将打包好的html,js,css静态资源放到镜像里,而不用在镜像中再打包,可以提高镜像的构建速度和减少镜像大小,从而提高应用交付的效率。比如在构建java应用的时候,我们只需要将jar包复制进去,在构建go应用的时候只需要将构建完的可执行文件放进去,然后使用CMD命令将之启动即可。

这里需要注意的是,尽量不要将整个项目拷贝进去,因为可能会涉及到源码泄露等安全问题(因为也可以将镜像的内容拷贝到本地),而且拷贝了无关的文件也会撑大镜像的体积,构建效率会大大缩减

ADD

添加文件,build的时候添加文件到image中 不仅仅局限于当前build上下文,可以来源于远程服务

ENV

环境变量, 指定build时候的环境变量 可以在启动的容器的时候 通过-e覆盖 格式ENV name=value,服务可以通过读取环境变量从而达到复用的效果,而不是在代码中写死,在构建镜像的时候,也方便扩展

ARG

构建参数,只在构建的时候使用的参数 如果有ENV那么ENV的相同名字的值始终覆盖arg的参数

VOLUME

定义外部可以挂载的数据卷, 指定buildimage那些目录可以启动的时候挂载到文件系统中,启动容器的时候使用-v 绑定,格式 VOLUME ["目录"],比如我们可以将配置文件挂载到数据卷,那么需要改动配置的时候,我们只需要在外部(宿主主机)的配置文件,然后重启容器即可,就不用进入容器中再修改了。比如可以将datalogs挂载到数据卷,防止容器销毁的时候数据丢失,在容器重新创建的时候,将这些数据卷再挂载回去,就会恢复之前的应用状态

我们在部署第三方镜像的时候,可以通过docker run -v命令来挂载数据卷,在生产中一定要挂载,不然容器被销毁了数据就全丢失了,一般官方给的部署示例中都会有

EXPOSE

暴露端口,定义容器运行的时候监听的端口 启动容器的使用-p来绑定暴露端口 格式:EXPOSE 8080或者 EXPOSE 8080/udp。 我们知道容器是封闭状态,外部是无法与容器通信的,我们可以通过暴露容器端口,将容器内部应用的端口映射出去,外部(宿主主机)就可以通过暴露的端口与容器进行通信了,这里要注意的是容器内占用的端口只是容器内的,不会占用宿主主机的端口

一般情况下,我们会run的时候指定

WORKDIR

工作目录,指定容器内部的工作目录 如果没有创建则自动创建,如果指定/ 使用的是绝对地址 如果不是/开头那么是在上一条workdir的路径的相对路径,我们可以将打包好的应用放到指定目录下去执行,这个跟我们在服务器指定目录下部署服务是一个道理

USER

指定执行用户,指定build或者启动的时候用户, 在RUN CMD ENTRYPONT执行的时候的用户

HEALTHCHECK

健康检查,指定监测当前容器的健康监测的命令,大部分情况下用不到,因为容器本身有检查机制

ONBUILD

触发器,当存在ONBUILD关键字的镜像作为基础镜像的时候 当执行FROM完成之后 会执行 ONBUILD的命令 但是不影响当前镜像 用处也不怎么大

STOPSIGNAL

发送信号量到宿主机,该STOPSIGNAL指令设置将发送到容器的系统调用信号以退出,这个也不是很常用

SHELL

指定执行脚本的shell,指定RUN CMD ENTRYPOINT 执行命令的时候 使用的shell,这个也不是很常用

命令介绍差不多了,下面就带大家从0构建SpringBoot的服务镜像

java 复制代码
@RestController
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class WepAppliation {

    @GetMapping("/hello")
    public String hello() {
        return "hello world!";
    }

    public static void main(String[] args) {
        SpringApplication.run(WepAppliation.class, args);
    }
}

默认情况下,8080端口,测试下http://localhost:8080/hello输出hello world!,应用没问题,接着开始打包,将jar包与Dockerfile位于通个目录下

接着准备Dockerfile

shell 复制代码
# 基础镜像
FROM openjdk:8-jre
# author
MAINTAINER pkq

# 挂载目录
VOLUME /root/java/app-web-docker
# 创建目录
RUN mkdir -p /app
# 指定路径
WORKDIR /app
# 复制jar文件到路径
COPY ./app-web.jar /app/app-web.jar
# 启动服务
ENTRYPOINT ["java", "-jar", "app-web.jar"]

这里我使用的基础镜像是openjdk:8-jre,这个是比较小的镜像,大家在选取基础镜像的时候,在满足需求的情况下尽可能的,动辄几个G的镜像那肯定是不行的,因为太大的镜像影响构建速度还会占用服务器的资源,如果要推送到远端仓库会比较慢

接着我们执行

shell 复制代码
>>>> docker build -t app-web .

[root@iZ2ze5vrnucj8nu52fq932Z app-web-docker]# docker build -t app-web .
Sending build context to Docker daemon 53.23 MB
Step 1/7 : FROM openjdk:8-jre
Trying to pull repository docker.io/library/openjdk ... 
8-jre: Pulling from docker.io/library/openjdk
0e29546d541c: Pull complete 
9b829c73b52b: Pull complete 
cb5b7ae36172: Pull complete 
99ce012bef04: Pull complete 
22dc2a72d098: Pull complete 
9c69a57e10d9: Pull complete 
Digest: sha256:c0ab1c0631266ef9420a414726a790733a2561efc5f4fa2f9b8186f4d6b00d53
Status: Downloaded newer image for docker.io/openjdk:8-jre
 ---> 26ac3f63d29f
Step 2/7 : MAINTAINER pkq
 ---> Running in 085e5fc91fac
 ---> 59c6ebf2ddba
Removing intermediate container 085e5fc91fac
Step 3/7 : VOLUME /root/java/app-web-docker
 ---> Running in 3aa1858ced18
 ---> 3ad95bbbe6ef
Removing intermediate container 3aa1858ced18
Step 4/7 : RUN mkdir -p /app
 ---> Running in ddce902c1044

 ---> a0434002b4ef
Removing intermediate container ddce902c1044
Step 5/7 : WORKDIR /app
 ---> 4ec0a0a8b000
Removing intermediate container 50b90491e870
Step 6/7 : COPY ./app-web.jar /app/app-web.jar
 ---> 4457507b2c81
Removing intermediate container 532dd4d4f748
Step 7/7 : ENTRYPOINT java -jar app-web.jar
 ---> Running in f8b25a13a3ae
 ---> e7ea93a81515
Removing intermediate container f8b25a13a3ae
Successfully built e7ea93a81515
[root@iZ2ze5vrnucj8nu52fq932Z app-web-docker]# 

[root@iZ2ze5vrnucj8nu52fq932Z app-web-docker]# docker images
REPOSITORY                                          TAG                 IMAGE ID            CREATED              SIZE
app-web                                             latest              e7ea93a81515        About a minute ago   327 MB

可以看到镜像已经构建成功了,下面运行测试一下

shell 复制代码
>>>docker run -it -d -p 10000:8080 --name app-web app-web 

5a9682238959ec7b54ba8cc2bff51d1494f6a1ac0e4bed4a97e330e0b0693328

[root@iZ2ze5vrnucj8nu52fq932Z app-web-docker]# docker logs -f app-web
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/app/app-web.jar!/BOOT-INF/lib/logback-classic-1.2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/app/app-web.jar!/BOOT-INF/lib/slf4j-simple-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.3.RELEASE)

2023-10-26 02:57:06.625  INFO 1 --- [           main] com.jbp.web.WepAppliation                : Starting WepAppliation v1.0-SNAPSHOT on 5a9682238959 with PID 1 (/app/app-web.jar started by root in /app)
2023-10-26 02:57:06.635  INFO 1 --- [           main] com.jbp.web.WepAppliation                : No active profile set, falling back to default profiles: default
2023-10-26 02:57:11.330  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2023-10-26 02:57:11.439  INFO 1 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2023-10-26 02:57:11.440  INFO 1 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.16]
2023-10-26 02:57:11.471  INFO 1 --- [           main] o.a.catalina.core.AprLifecycleListener   : The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: [/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib]
2023-10-26 02:57:11.664  INFO 1 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2023-10-26 02:57:11.664  INFO 1 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 4845 ms
2023-10-26 02:57:13.455  INFO 1 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2023-10-26 02:57:14.718  INFO 1 --- [           main] o.s.b.a.e.web.EndpointLinksResolver      : Exposing 2 endpoint(s) beneath base path '/actuator'
2023-10-26 02:57:15.027  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2023-10-26 02:57:15.042  INFO 1 --- [           main] com.jbp.web.WepAppliation                : Started WepAppliation in 9.563 seconds (JVM running for 10.509)

看到已经运行成功了,试试请求是否成功,因为我暴露的10000端口,所以请求curl http://localhost:10000/hello

shell 复制代码
[root@iZ2ze5vrnucj8nu52fq932Z app-web-docker]# curl http://localhost:10000/hello
hello world!

[root@iZ2ze5vrnucj8nu52fq932Z app-web-docker]# 

可以看到成功运行了~ 大家可以举一反三,试着构建一些其它服务

结束语

本节到这里就结束了,docker命令很多,大家不要去背,如果忘了可以使用docker -h进行查看,多动手,多尝试,多踩坑,下节继续给大家讲解它的用法~

本着把自己知道的都告诉大家,如果本文对有所帮助,点赞+关注鼓励一下呗~

Docker教程相关文章

往前Shell脚本编程相关文章

往期Linux相关文章

往期面试题相关文章

项目源码(源码已更新 欢迎star⭐️)

往期设计模式相关文章

设计模式项目源码(源码已更新 欢迎star⭐️)

Kafka 专题学习

项目源码(源码已更新 欢迎star⭐️)

ElasticSearch 专题学习

项目源码(源码已更新 欢迎star⭐️)

往期并发编程内容推荐

推荐 SpringBoot & SpringCloud (源码已更新 欢迎star⭐️)

博客(阅读体验较佳)

相关推荐
无名指的等待71242 分钟前
SpringBoot中使用ElasticSearch
java·spring boot·后端
.生产的驴1 小时前
SpringBoot 消息队列RabbitMQ 消费者确认机制 失败重试机制
java·spring boot·分布式·后端·rabbitmq·java-rabbitmq
AskHarries2 小时前
Spring Boot利用dag加速Spring beans初始化
java·spring boot·后端
神秘的土鸡2 小时前
Linux中使用Docker容器构建Tomcat容器完整教程
linux·运维·服务器·docker·容器·tomcat
玖石书2 小时前
docker 数据管理
docker·容器
苹果酱05672 小时前
一文读懂SpringCLoud
java·开发语言·spring boot·后端·中间件
掐指一算乀缺钱3 小时前
SpringBoot 数据库表结构文档生成
java·数据库·spring boot·后端·spring
2420304 小时前
Docker笔记-容器数据卷
docker
计算机学姐5 小时前
基于python+django+vue的影视推荐系统
开发语言·vue.js·后端·python·mysql·django·intellij-idea
JustinNeil5 小时前
简化Java对象转换:高效实现大对象的Entity、VO、DTO互转与代码优化
后端