一起来学Docker(六)

简介: 一起来学Docker(六)

前言

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

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

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

构建镜像

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

语法:

docker build [OPTIONS] PATH | URL | -

OPTIONS说明:

--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,我们可以这么写:

docker build -t web/web:latest . 

当然也可以指定文件:

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的服务镜像

@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

# 基础镜像
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的镜像那肯定是不行的,因为太大的镜像影响构建速度还会占用服务器的资源,如果要推送到远端仓库会比较慢

接着我们执行

>>>> 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

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

>>>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

[root@iZ2ze5vrnucj8nu52fq932Z app-web-docker]# curl http://localhost:10000/hello
hello world!
[root@iZ2ze5vrnucj8nu52fq932Z app-web-docker]# 

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

结束语

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

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

相关文章
|
NoSQL 安全 Redis
|
6月前
|
Java Linux 虚拟化
|
7月前
|
关系型数据库 MySQL Shell
|
7月前
|
Linux Go 开发者
Docker(一):认识Docker
Docker(一):认识Docker
|
7月前
|
JavaScript Linux Docker
【Docker】什么是Docker?
【4月更文挑战第20天】【Docker】什么是Docker?
|
7月前
|
存储 运维 Linux
|
Docker 容器
|
JavaScript 应用服务中间件 API
Docker
Docker 是一种开源的容器化平台,可以让开发者在容器中快速构建、打包、发布和运行应用程序,从而实现应用程序的快速交付和部署。
472 1
|
NoSQL Java Redis
了解和使用Docker
本文对 Docker 进行全面阐述,详细介绍 Docker 的作用、其基本使用,如常用命令、Dockerfile 的作用及使用、Docker Compose 的作用及使用。常用的基本上都会涉及,其他可以在[ Docker 官网](https://docs.docker.com/)进行查漏补缺。
146 0
|
存储 持续交付 虚拟化