一起来学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⭐️)

博客(阅读体验较佳)

相关推荐
码农小旋风1 小时前
详解K8S--声明式API
后端
Peter_chq1 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
Yaml42 小时前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍
小小小妮子~2 小时前
Spring Boot详解:从入门到精通
java·spring boot·后端
hong1616882 小时前
Spring Boot中实现多数据源连接和切换的方案
java·spring boot·后端
追风林2 小时前
mac 本地docker-mysql主从复制部署
mysql·macos·docker
睡觉谁叫~~~3 小时前
一文解秘Rust如何与Java互操作
java·开发语言·后端·rust
城南vision4 小时前
Docker学习—Docker核心概念总结
java·学习·docker
wclass-zhengge4 小时前
Docker篇(Docker Compose)
运维·docker·容器
2401_865854885 小时前
iOS应用想要下载到手机上只能苹果签名吗?
后端·ios·iphone