【零基础入门Docker】Dockerfile中的USER指令以及dockerfile命令详解

面向读者:所有人

所属专栏:Docker零基础入门专栏

目录

第 1 步:创建 Dockerfile

第 2 步:构建 Docker 镜像

第 3 步:运行 Docker 容器

第 4 步:验证输出

dockerfile命令详解

最佳实践

默认情况下,Docker 容器以 Root 用户身份运行。如果您在 Docker 容器内大规模部署应用程序,这会带来巨大的安全威胁。您可以使用USER指令更改或切换到 Docker 容器内的不同用户。为此,您首先需要在容器内创建一个用户和一个组。

在本文中,我们将使用USER指令将容器内的用户从 Root 切换到我们将创建的用户。为此,请按照以下步骤操作:

第 1 步:创建 Dockerfile

您可以在Dockerfile中指定创建新用户和组以及切换用户的指令。在此示例中,我们将简单地创建一个 Ubuntu 映像,并通过除 Root 用户之外的其他用户来使用 bash。

FROM ubuntu:latest
RUN apt-get -y update
RUN groupadd -r user && useradd -r -g user user
USER user

在上面的dockerfile中,我们已经拉取了基础镜像 Ubuntu 并更新了它。我们创建了一个名为user的新组,并在该组内创建了一个具有相同名称的新用户。使用USER选项,我们已经切换了用户。

第 2 步:构建 Docker 镜像

创建Dockerfile后,我们现在可以使用 Build 命令创建 Docker 映像。

sudo docker build -t user-demo 

第 3 步:运行 Docker 容器

使用 Docker Run 命令来运行容器。

sudo docker run -it user-demo bash

第 4 步:验证输出

现在,您可以使用id命令检查默认用户和组是否已更改为我们在Dockerfile中创建的用户和组。

id

总之,在本文中,我们讨论了如何使用Dockerfile中的USER指令将 Docker 容器的默认用户从 Root 切换到我们可以使用useraddgroupadd命令创建的另一个用户。 

Dockerfile 是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。有了 Dockerfile,当我们需要定制自己额外的需求时,只需在 Dockerfile 上添加或者修改指令,重新生成 image 即可,省去了敲命令的麻烦。

基础镜像信息
FROM      第一条指令必须为FROM指令,并且,如果在同一个Dockerfile中创建多个镜像时,可以使用多个FROM指令(每个镜像一次)
MAINTAINET 指定维护者的信息。
Label    给构建的镜像打标签。
镜像操作指令
RUN     每条指令将在当前镜像基础上执行,并提交为新的镜像。(可以用“\”换行)
CMD     指定启动容器时执行的命令,每个Dockerfile只能有一条CMD指令,如果指定了多条指令,则最后一条执行。(会被启动时指定的命令覆盖)
ADD     复制指定的到容器的中,可以是Dockerfile所在的目录的一个相对路径;可以是URL,也可以是tar.gz(自动解压)
COPY    复制本地主机的( 为 Dockerfile 所在目录的相对路径)到容器中的(当使用本地目录为源目录时,推荐使用 COPY)
WORKDIR 为后续的 RUN 、 CMD 、 ENTRYPOINT 指令配置工作目录。(可以使用多个 WORKDIR 指令,后续命令如果参数是相对路径, 则会基于之前命令指定的路径)
EXPOSE  告诉Docker服务端暴露端口,在容器启动时需要通过 -p 做端口映射
VOLUME  创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等
USER    指定运行容器时的用户名或 UID,后续的 RUN 也会使用指定用户。
ONBUILD 配置当所创建的镜像作为其它新创建镜像的基础镜像时,所执行的操作指令

容器启动时执行指令
ENV     指定环境变量,会被RUN指令使用,并在容器运行时保存
ENTRYPOINT     配置容器启动后执行的命令,并且不可被 docker run 提供的参数覆盖。(每个 Dockerfile 中只能有一个 ENTRYPOINT ,当指定多个时,只有最后一个起效)
实例
FROM openjdk:8-jdk-alpine
MAINTAINER Kurisu "makise_kurisuu@outlook.jp"
LABEL maintainer="makise_kurisuu@outlook.jp"
VOLUME /tmp
ARG JAR_FILE=target/alice-server.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

dockerfile命令详解

FROM  构建的镜像设置基础镜像FROM <image> [AS <name>] FROM <image>[:<tag>] [AS <name>] FROM <image>[@<digest>] [AS <name>]FROM指令初始化新的构建阶段,并为后续指令设置基础镜像,FROM openjdk:8-jdk-alpine。因此,Dockerfile文件必须以FROM指令开头。 而指定的镜像可以使任何有效的镜像(推荐使用公共仓库的镜像,因为拉取更为容易)。在Dockerfile文件中ARG是唯一一个可以用于FROM之前的指令ARG CODE_VERSION=latest FROM base:${CODE_VERSION} CMD /code/run-app FROM extras:${CODE_VERSION} CMD /code/run-extras
  MAINTAINET  指定维护者的信息  格式:MAINTAINET <name>
LABLE  给构建的镜像打标签格式:LABEL <key>=<value> <key>=<value> <key>=<value> ...
RUN 在镜像的构建过程中执行特定的命令,并生成一个中间镜像。比如安装一些软件、配置一些基础环境,可使用\来换行。
  RUN <command> (shell格式)  RUN ["executable", "param1", "param2"] (exec格式)
要注意的是,executable是命令,后面的param是参数采用exec格式指令将会被解析成json格式所以不能使用单引号,并且使用反斜杠也是必须要转移的,这在windows上尤为重要。
CMD 指定容器运行时的默认参数
CMD ["executable","param1","param2"](exec格式,首选)CMD ["param1","param2"](给ENTRYPOINT提供默认参数)CMD command param1 param2(shell格式)
注意:RUN是在构建的时候执行,并生成一个新的镜像,CMD在构建时不进行任何操作,在容器运行的时候执行。如果CMD用于为ENTRYPOINT指令提供缺省参数,那么CMD和ENTRYPOINT指令都应该使用JSON数组格式。
ADD 构建镜像时,复制上下文中的文件到镜像内。
ADD <src>... <dest>ADD ["<src>",... "<dest>"](路径包含空格的必须使用这种格式)

<src>可以是文件、目录,也可以是文件URL。可以使用模糊匹配(wildcards,类似shell的匹配),可以指定多个<src>,必须是在上下文目录和子目录中, 无法添加../a.txt这样的文件。如果<src>是个目录,则复制的是目录下的所有内容,但不包括该目录。如果<src>是个可被docker识别的压缩包, docker会以tar -x的方式解压后将内容复制到<desct>。<dest>可以是绝对路径,也可以是相对WORKDIR目录的相对路径。 所有文件的UID和GID都是0
 

COPY 将主机的文件复制到镜像内,如果目的位置不存在,Docker会自动创建所有需要的目录结构,但是它只是单纯的复制,并不会去做文件提取和解压工作COPY <src>... <dest>COPY ["<src>",... "<dest>"](路径包含空格的必须使用这种格式)注意:需要复制的目录一定要放在Dockerfile文件的同级目录下。因为构建环境将会上传到Docker守护进程,而复制是在Docker守护进程中进行的。任何位于构建环境之外的东西都是不可用的。 COPY指令的目的的位置则必须是容器内部的一个绝对路径。
 
WORKDIR 为接下来的Dockerfile指令指定当前工作目录,可多次使用,如果使用的是相对路径,则相对的是上一个工作目录,类似shell中的cd命令。WORKDIR /path/to/workdir受影响的指令有:RUN、CMD、ENTRYPOINT、COPY和ADD。 可以在Dockerfile中多次使用WORKDIR指令。如果提供了相对路径,则它将相对于上一个WORKDIR指令的路径。例如:WORKDIR /aWORKDIR bWORKDIR cRUN pwd此Dockerfile中pwd指令将输出 /a/b/c.。WORKDIR指令可以解析之前使用ENV设置的环境变量,只能使用Dockerfile中显式设置的环境变量。例如:ENV DIRPATH /pathWORKDIR $DIRPATH/$DIRNAMERUN pwd此Dockerfile中pwd指令将输出 /path/$DIRNAME。
 
EXPOSE 为构建的镜像设置监听端口。EXPOSE <port> [<port>/<protocol>...]EXPOSE指令让docker容器在运行的时候监听指定的端口,可以指定端口是upd还是tcp协议,如果没有指定则默认tcp协议。EXPOSE指令并不会发布端口,如果发布端口,则需要在docker run时使用-p来发布和映射一个或多个容器端口、或者使用-P来发布所有公开的端口并将它们映射到高阶端口。
 
VOLUME 指定镜像内的目录为数据卷。VOLUME ["/data"]在容器运行的时候,docker会把镜像中的数据卷的内容复制到容器的数据卷中去。 如果在接下来的Dockerfile指令中,修改了数据卷中的内容,则修改无效。
 
USER 为接下来的Dockerfile指令指定用户。受影响的指令有:RUN、CMD、ENTRYPOINT。USER <user>[:<group>] orUSER <UID>[:<GID>]注意:当用户没有主要组时,镜像(或下一条指令)将与该root组一起运行
 
ONBUILD 向镜像中添加一个触发器,当以该镜像为基础镜像再次构建新的镜像时,会触发执行其中的指令。ONBUILD [INSTRUCTION]比如我们生成的镜像是用来部署Python代码的,但是因为有多个项目可能会复用该镜像。你可以这样使用:[...]# 在下一次以此镜像为base image的构建中,执行ADD . /app/src,将项目代目添加到新镜像中去ONBUILD ADD . /app/src# 并且build Python代码ONBUILD RUN /usr/local/bin/python-build --dir /app/src[...]不允许ONBUILD使用链接指令ONBUILD ONBUILD。ONBUILD只会继承给子节点的镜像,不会再继承给孙子节点。ONBUILD不会触发FROM、MAINTAINER指令。
ENV 在构建的镜像中设置环境变量,在后续的Dockerfile指令中可以直接使用,也可以固化在镜像里,在容器运行时仍然有效。 ENV指令有两种格式:ENV :把第一个空格之后的所有值都当做的值,无法在一行内设定多个环境变量。ENV = ...:可以设置多个环境变量,如果中存在空格,需要转义或用引号"括起来。ENV myName John DoeENV myDog Rex The DogENV myCat fluffy或者
ENV myName="John Doe" myDog=Rex\ The\ Dog \    myCat=fluffy推荐使用第二种,同样的这样能减少图层提高效率。
注意:可以在容器运行时指定环境变量,替换镜像中的已有变量,docker run --env <key>=<value>。使用ENV可能会对后续的Dockerfile指令造成影响,如果只需要对一条指令设置环境变量,可以使用这种方式:RUN <key>=<value> <command>
ENTRYPOINT 指定镜像的执行程序。ENTRYPOINT指令有两种格式:ENTRYPOINT ["executable", "param1", "param2"] (执行格式,首选)ENTRYPOINT command param1 param2 (shell格式)CMD和ENTRYPOINT至少得使用一个。ENTRYPOINT应该被当做docker的可执行程序,CMD应该被当做ENTRYPOINT的默认参数。docker run <image> <arg1> <arg2> ...会把之后的参数传递给ENTRYPOINT,覆盖CMD指定的参数。可以用docker run --entrypoint来重置默认的ENTRYPOINT。
 
STOPSIGNAL 触发系统信号。STOPSIGNAL signalSTOPSIGNAL指令设置将发送到容器以退出的系统调用信号。此信号可以是与内核的SysCall表中的位置匹配的有效无符号数字(例如9),也可以是格式为SIGNAME的信号名称(例如SIGKILL)。
HEALTHCHECK 增加自定义的心跳检测功能,多次使用只有最后一次有效。格式:HEALTHCHECK [OPTIONS] CMD command (通过在容器内运行命令来检查容器运行状况)HEALTHCHECK NONE (禁用从基础映像继承的任何运行状况检查)可选的OPTION:
--interval=DURATION(检测间隔,默认值:30s)--timeout=DURATION(命令超时时间,默认值:30s)--start-period=DURATION(初始化后开始检查时间,默认值:0s)--retries=N(连续N次失败后标记为不健康,默认值:3次)Start Period为需要时间引导的容器提供初始化时间。在此期间的探测失败将不计入最大重试次数。但是,如果运行状况检查在开始期间成功,则容器将被视为已启动,并且所有连续失败将计入最大重试次数。
<command>可以是shell脚本,也可以是exec格式的json数组。docker以<command>的退出状态码来区分容器是否健康,这一点同shell一致:
0:命令返回成功,容器健康1:命令返回失败,容器不健康2:保留状态码,不要使用举个栗子:每5分钟检测本地网页是否可访问,超时设为3秒:
HEALTHCHECK --interval=5m --timeout=3s \  CMD curl -f http://localhost/ || exit 1复制代码你可以使用docker inspect命令查看健康状态。当容器的运行状况发生更改时,将生成带有新状态的health_status事件
SHELL更改后续的Dockerfile指令中所使用的shell。默认的shell是["bin/sh", "-c"]。可多次使用,每次都只改变后续指令。
SHELL ["executable", "parameters"]
 
特别注意在上面的描述中可以看到有两组指令在功能上都差不多,但也是有区别的:
RUN、CMD、ENTRYPOINT执行脚本的指令三个指令都是执行脚本RUN是在创建镜像是执行,即使用docker build命令时执行,在一个Dockerfile里面可以有多个RUNCMD和ENTRYPOINT是在运行容器时执行,即使用docker run命令时执行,这两个指令在Dockerfile中都只有最行一条被执行CMD在使用docker run时可以加参数将Dockerfile中的CMD覆盖ENTRYPOINT在Dockerfile中出现后就一定会在docker run时被执行,不必担心会被其他参数所覆盖。ADD、COPY拷贝文件(夹)到容器ADD拷贝文件(夹)时可以指定本地文件、远程URL地址,如果拷贝的是tar文件时将会被自动解压成文件夹COPY拷贝文件(夹)时不可以指定远程URL地址,拷贝tar文件也不会被自动解压成文件夹,在拷贝本地文件时建议使用COPY

最佳实践

容器应该是短暂的

通过 Dockerfile 构建的镜像所启动的容器应该尽可能短暂 (ephemeral)。短暂意味着可以很快地启动并且终止

使用 .dockerignore 排除构建无关文件

.dockerignore 语法与 .gitignore 语法一致。使用它排除构建无关的文件及目录,如 node_modules

使用多阶段构建

多阶段构建可以有效减小镜像体积,特别是对于需编译语言而言,一个应用的构建过程往往如下

  1. 安装编译工具
  2. 安装第三方库依赖
  3. 编译构建应用

而在前两步会有大量的镜像体积冗余,使用多阶段构建可以避免这一问题

避免安装不必要的包

减小体积,减少构建时间。如前端应用使用 npm install --production 只装生产环境所依赖的包。

一个容器只做一件事

如一个web应用将会包含三个部分,web 服务,数据库与缓存。把他们解耦到多个容器中,方便横向扩展。如果你需要网络通信,则可以将他们至于一个网络下。

减少镜像层数

只有 RUN, COPY, ADD 会创建层数, 其它指令不会增加镜像的体积
尽可能使用多阶段构建
使用以下方法安装依赖

RUN yum install -y node python go

将多行参数排序

便于可读性以及不小心地重复装包

 
RUN apt-get update && apt-get install -y \
bzr \
cvs \
git \
mercurial \
subversion

充分利用构建缓存

在镜像的构建过程中 docker 会遍历 Dockerfile 文件中的所有指令,顺序执行。对于每一条指令,docker 都会在缓存中查找是否已存在可重用的镜像,否则会创建一个新的镜像。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/208679.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

oops-framework框架 之 初始了解(一)

引擎&#xff1a;CocosCreator 环境&#xff1a; Mac Gitee: oops-framework 简介 oops-framework是由作者dgflash编写&#xff0c;基于CocosCreator 3.x而实现的开源框架。 该框架以插件形式存在&#xff0c;主要目的是为了降低与项目的耦合&#xff0c;并且通过插件内部的…

【LeetCode:1657. 确定两个字符串是否接近 | 计数 + 阅读理解】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

若依前后端分离版idea启动

1.项目地址 https://gitee.com/y_project/RuoYi-Vue2.修改配置 修改数据库配置 3.执行sql 4.启动项目 启动成功 5.启动前端 首先要安装nodejs,版本不能太高,本人用的nodejs11版本的 npm install --registry https://registry.npm.taobao.orgnpm run dev启动成功 访问 h…

态路小课堂丨InfiniBand与以太网:AI时代的网络差异

近年来&#xff0c;随着人工智能技术的迅猛发展&#xff0c;以ChatGPT为代表的大型AI模型引起了广泛关注。然而&#xff0c;在这个AI时代&#xff0c;我们不得不重新审视传统的以太网和基于InfiniBand构建的网络之间的区别。尤其是今年以来&#xff0c;InfiniBand因其在AI领域中…

CRM:如何通过客户数据分析获得业务洞察?

客户数据分析&#xff0c;也称客户分析&#xff0c;是收集、组织和分析客户数据&#xff0c;以深入了解客户行为的过程。企业将利用这些数据来制定与营销、产品开发、销售等相关的业务决策。 通过客户分析&#xff0c;你可以做出简单的业务决策&#xff0c;比如找出投资回报率…

景联文科技数据标注平台助力AI数据实现价值最大化

随着人工智能技术不断进步&#xff0c;应用领域不断拓宽&#xff0c;对于高质量、大规模标注数据的需求也在不断增加。 数据标注是人工智能行业的基石。机器学习需要运用海量的有效数据来做支撑&#xff0c;而这些数据就需要我们的标注员对其进行分析和处理&#xff0c;想要得到…

【力扣周赛】第 369 场周赛(⭐记忆化搜索 树形DP)

文章目录 竞赛链接Q1&#xff1a;2917. 找出数组中的 K-or 值竞赛时代码——按题意模拟 Q2&#xff1a;2918. 数组的最小相等和竞赛时代码——分类讨论 Q3&#xff1a;2919. 使数组变美的最小增量运算数⭐⭐⭐竞赛时代码——动态规划解法2——记忆化搜索 翻译成递推 Q4&#xf…

HarmonyOS ArkTS与c++交互通信

一、创建Native C Module 1、右键项目->new->module 如图&#xff1a; 2、修改build-profile.json5配置 "externalNativeOptions": {"path": "./src/main/cpp/CMakeLists.txt","arguments": "-v -DOHOS_STLc_shared&quo…

带你用uniapp从零开发一个仿小米商场_10.开发一个占剩余窗口的滚动区域

首先是一个头部的tag切换栏,这个很简单,就不多说 源码奉上 <scroll-view scroll-x class"border scroll-row" style"height: 80rpx;"><view class"scroll-row-item" style"height: 80rpx;line-height: 80rpx;" v-for"(…

数学建模之相关系数模型及其代码

发现新天地&#xff0c;欢迎访问小铬的主页(www.xiaocr.fun) 引言 本讲我们将介绍两种最为常用的相关系数&#xff1a;皮尔逊pearson相关系数和斯皮尔曼spearman等级相关系数。它们可用来衡量两个变量之间的相关性的大小&#xff0c;根据数据满足的不同条件&#xff0c;我们要…

PyTorch入门教学——加载数据(Dataloader)

1、简介 PyTorch中如何读取数据主要涉及到两个类&#xff0c;分别为Dataset和Dataloader。 Dataset&#xff1a;创建可被Pytorch使用的数据集Dataloader&#xff1a;向模型传递数据本文主要讲解Dataloader的使用方法。 2、Dataloader 2.1、查看使用方法 查看官网文档&#…

matlab simulink PMSM电机转速预估

1、内容简介 略 22-可以交流、咨询、答疑 2、内容说明 PMSM电机转速预估 PMSM电机转速预估 PMSM、转速估计&#xff0c;PID控制 3、仿真分析 略 4、参考论文 略 链接&#xff1a;https://pan.baidu.com/s/1AAJ_SlHseYpa5HAwMJlk1w 提取码&#xff1a;rvol

计算机视觉(OpenCV+TensorFlow)

计算机视觉&#xff08;OpenCVTensorFlow&#xff09; 文章目录 计算机视觉&#xff08;OpenCVTensorFlow&#xff09;前言3.图像金字塔3.1 高斯金字塔3.2 拉普拉斯金字塔 4.图像轮廓图像边缘和图像轮廓的区别检测图像绘制边缘 5.轮廓近似外接矩形外接圆 6. 模板匹配6.1 什么是…

LeetCode 1212 查询球队积分(PostgreSQL)

数据准备 Create table If Not Exists Teams (team_id int, team_name varchar(30)) Create table If Not Exists Matches (match_id int, host_team int, guest_team int, host_goals int, guest_goals int) Truncate table Teams insert into Teams (team_id, team_name) va…

关于pytorch安装成功后No module name ‘torch‘的解决方法

一、pytorch环境配置 1、Pytorch 的安装 &#xff08;1&#xff09;单击启动 Anaconda Prompt 创建虚拟房间 &#xff08;2&#xff09;输入py -0p查看当前python版本 或者这里不清楚自己 python 版本的可以 cmd 命令行输入 python 查询 &#xff08;3&#xff09;输入命令…

Jetson Nano部署YOLOv5与Tensorrtx加速

一、烧录镜像 1、Jetson Nano烧写系统镜像 Jetson Nano是一款形状、外接口类似于树莓派的嵌入式主板&#xff0c;搭载了四核Cortex-A57处理器&#xff0c;GPU则是拥有128个NVIDIA CUDA核心的NVIDIA Maxwell架构显卡&#xff0c;内存为4GB的LPDDR4&#xff0c;存储则为16GB eM…

『 Linux 』环境变量

文章目录 &#x1f680;什么是环境变量&#x1f680;&#x1f680;查看环境变量&#x1f680;&#x1f579;️和环境变量有关的命令&#x1f579;️ &#x1f680;PATH环境变量&#x1f680;&#x1f579;️设置PATH环境变量&#x1f579;️ &#x1f680;HOME环境变量&#x1…

vue 前端实现login页登陆 验证码

实现效果 // template <el-form :model"loginForm" :rules"fieldRules" ref"loginForm" label-position"left" label-width"0px" class"login-container"><span class"tool-bar"></sp…

解决VSCode按住Ctrl(or Command) 点击鼠标左键不跳转的问题(不能Go to Definition)

问题出现 往往在升级了VSCode以后&#xff0c;就会出现按住Ctrl&#xff08;or Command&#xff09; 点击鼠标左键不跳转的问题&#xff0c;这个问题很常见。 解决办法 1 进入VScode的首选项&#xff0c;选择设置 2 输入Go to definition&#xff0c;找到如下两个设置&#…

逸学java【初级菜鸟篇】11.多线程【多方位详解】

hi&#xff0c;我是逸尘&#xff0c;一起学java吧 目标&#xff08;任务驱动&#xff09; 本章没有任务目标&#xff0c;略述概述多线程一隅&#xff0c;全是精华。 线程 进程 在提到线程是什么之前我们还需要提到另一个名词 他就是进程 进程&#xff1a;是指一个内存中运…