文章目录
一:docker中容器与常规的虚拟化平台中虚拟机的区别
1.1 隔离与共享
虚拟机通过添加Hypervisor(管理程序程序虚拟层),虚拟出网卡、内存、CPU等虚拟硬件,再在其上建立虚拟机,每个虚拟机都有自己的系统内核。
而Docker容器则是通过隔离的方式,将文件系统、进程、设备、网络等资源进行隔离,再对权限、CPU资源等进行控制,最终让容器之间互不影响,容器无法影响宿主机。容器与宿主机共享内核、文件系统、硬件等资源。
1.2 性能与损耗
与虚拟机相比,容器资源损耗要少。同样的宿主机下,能够建立容器的数量要比虚拟机多。
但是,虚拟机的安全性要比容器稍好,要从虚拟机攻破到宿主机或者其他虚拟机,就需要先攻破Hypervsior,但是极其困难。
而docker容器与宿主机共享内核、文件系统等资源,更有可能对其他容器、宿主机产生影响。
二:Docker存在的安全问题
2.1 Docker自身漏洞
作为一款应用Docker本身实现上会有代码缺陷,在官方记录Docker历史版本工作共有超过20项漏洞。
黑客常用的攻击手段主要有代码执行、权限提升、信息泄露、权限绕过等。目前Docker版本更迭非常快,Docker用户最好将Docker升级为最新版本。
docker更新考虑的第一个就是安全,然后就是资源利用率
2.2 Docker源码问题
Docker提供了Docker hub(公有仓库),可以让用户上传创建的镜像,以便其他用户下载,快速搭建环境。但同时也带来了一些安全隐患。例如下面三种方式:
2.2.1 黑客上传恶意镜像
如果有黑客在制作的镜像中植入木马、后门等恶意团建,那么环境一开始就变得不安全,后续更没有安全可言。
2.2.2 镜像中使用有漏洞的软件
Docker hub上能下载的镜像里面,有一大部分都安装了有漏洞的软件;所以下载镜像后,需要检查里面软件的版本信息,对应的版本是否存在漏洞,并及时更新打赏补丁
2.2.3 中间人攻击篡改镜像
镜像在传输过程中可能被篡改,目前新版本的Docker已经提供了相应的校验机制来预防这个问题。
三:Docker架构缺陷与安全机制
docker本身的架构与机制就可能产生问题。例如这样一种攻击场景,黑客已经控制了宿主机上的一些容器,或者获得了通过在共有公国云上建立容器的方式,然后对宿主机或其他容器发起了攻击。
3.1 容器之间的局域网攻击
主机上的容器之间可以构成局域网,因此针对局域网的ARP欺骗、嗅探、广播风暴等攻击方式可能会出现
所以,在一个主机上部署多个容器需要合理的配置网络,设置iptables规则
3.2 DDos攻击耗尽资源
DDos攻击:就是占用资源但是不干活
Cgroups资源配额安全机制就是要防止此类攻击的,不要为单一地容器分配过多的资源即可避免此类问题
3.3 有漏洞的系统调用
Docker与虚拟机的一个重要的区别就是Docker与宿主机共用一个操作系统内核。
一旦宿主内核存在可以越权或者提权漏洞,尽管Docker使普通用户执行,在容器被入侵时,攻击者还可以利用内核漏洞跳到宿主机做更多的事情
3.4 共享root用户权限
如果以root用户权限运行容器,容器内的root用户也就拥有了宿主机的root权限
四:Docker安全基线标准
下面从内核、主机、网络、镜像、容器以及其它等6个方面总结Docker安全基线标准。
4.1 内核级别
1.及时更新内核
2.User NameSpace(容器内的root权限在容器之外处于非高权限状态)。
3.Cgroups(对资源的配额的度量)。
4.SELinux/AppArmor/GRSEC(控制文件访问权限)。
5.Capability(权限划分)。
6.Seccomp(限定系统调用)。
7.禁止将容器的命名空间与宿主机进程命名空间共享。
4.2 主机级别
1.为容器创建独立存储分区
2.仅运行必要的服务
3.禁止将宿主机上敏感目录映射到容器
4.对Docker守护进程、相关文件和目录进行审计
5.设置适当的默认文件描述符数
(文件描述符:内核(kernel)利用文件描述符(file descriptor)来访问文件。文件描述符是非负整数。打开现存文件或新建文件时,内核会返回一个文件描述符。读写文件也需要文件描述符来指定待读写的文件)
6.用户权限为root的Docker相关文件的访问权限应该为644或者更低权限。
7.周期性检查每个主机的容器清单,并清理不必要的容器
一台服务器可以预留两个网卡端口,用来做负载均衡等流量转发
4.3 网络级别
1.通过iptables设定规则实现禁止或允许容器之间网络流量
2.允许docker修改iptables
3.禁止将docker绑定到其他IP/port或者unix socket
4.禁止在容器上映射特权端口,就是别映射已用端口
5.容器上只开放所需要的端口
6.禁止在容器上使用主机网络(host)模式
7.若宿主机有多个网卡,将容器进入流量绑定到特定的主机网卡上
4.4 镜像级别
1.创建本地镜像仓库服务器
2.镜像中软件都为最新本版本。
3.使用可信镜像文件,并通过安全通道下载
4.重新构建镜像而非对容器和镜像打补丁
5.合理管理镜像标签,及时移除不再使用的镜像
6.使用镜像扫描
7.使用镜像签名
4.5 容器级别
1.容器最小化,操作系统镜像最小化
2.容器以单一主进程的方式运行
3.禁止使用–privileged标记使用特权容器
4.禁止在容器上运行ssh服务
5.以只读的方式挂载容器的根目录系统
6.明确定义属于容器的数据盘符
7.通过设置on-failure限制容器常识重启的次数,容器反复重启容易丢失数据
8.限制在容器中可用的进程数,以防止fork bomb(迅速增长子进程,耗尽系统进程数量)
4.6 其他设置
1.定期对宿主机系统及容器进行安全审计
2.使用最少资源和最低权限运行容器
3.避免在统一宿主机上部署大量容器,维持在一个能够管理的数量
4.监控Docker容器的使用,性能以及其他各项指标
5.增加实时威胁检测和时间相应功能
6.使用中心和远程日志收集服务
k8s或者zabbix可以监控docker
五:使用本地登录容器实现最小化
如果尽在容器中运行必要的服务,像SSH等服务是不能轻易开启去链接容器的;
通常使用本exec 去链接进入容器
docker exec -itt 容器ID bash
六:Docker remote( 远程调用) api访问控制
docker的远程调用API接口存在未授权访问漏洞,至少应限制外网访问
建议使用Socket方式访问,socket 是使用tcp协议访问
6.1 环境如下
当前docker镜像(安装harbor仓库)
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
compose_nginx_nginx latest e3abfd076454 4 days ago 726MB
cirros latest 3c82e4d066cf 7 weeks ago 12.6MB
127.0.0.1/gsy/cirros vers1 3c82e4d066cf 7 weeks ago 12.6MB
centos 7 5e35e350aded 5 months ago 203MB
vmware/harbor-log v1.2.2 36ef78ae27df 2 years ago 200MB
vmware/harbor-jobservice v1.2.2 e2af366cba44 2 years ago 164MB
vmware/harbor-ui v1.2.2 39efb472c253 2 years ago 178MB
vmware/harbor-adminserver v1.2.2 c75963ec543f 2 years ago 142MB
vmware/harbor-db v1.2.2 ee7b9fa37c5d 2 years ago 329MB
vmware/nginx-photon 1.11.13 6cc5c831fc7f 2 years ago 144MB
vmware/registry 2.6.2-photon 5d9100e4350e 2 years ago 173MB
vmware/postgresql 9.6.4-photon c562762cbd12 2 years ago 225MB
vmware/clair v2.0.1-photon f04966b4af6c 2 years ago 297MB
vmware/harbor-notary-db mariadb-10.1.10 64ed814665c6 3 years ago 324MB
vmware/notary-photon signer-0.5.0 b1eda7d10640 3 years ago 156MB
vmware/notary-photon server-0.5.0 6e2646682e3c 3 years ago 157MB
photon 1.0 e6e4e4a2ba1b 3 years ago 128MB
当前docker up容器
[root@docker ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
94630e81bb21 vmware/harbor-jobservice:v1.2.2 "/harbor/harbor_jobs…" 2 days ago Up 2 days harbor-jobservice
e68e275ba6c5 vmware/nginx-photon:1.11.13 "nginx -g 'daemon of…" 2 days ago Up 2 days 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp, 0.0.0.0:4443->4443/tcp nginx
278c281594c9 vmware/harbor-ui:v1.2.2 "/harbor/harbor_ui" 2 days ago Up 2 days harbor-ui
b7adea7dfc28 vmware/registry:2.6.2-photon "/entrypoint.sh serv…" 2 days ago Up 2 days 5000/tcp registry
b587a5b5a4f9 vmware/harbor-db:v1.2.2 "docker-entrypoint.s…" 2 days ago Up 2 days 3306/tcp harbor-db
8fbb66df3206 vmware/harbor-adminserver:v1.2.2 "/harbor/harbor_admi…" 2 days ago Up 2 days harbor-adminserver
b282d0c45952 vmware/harbor-log:v1.2.2 "/bin/sh -c 'crond &…" 2 days ago Up 2 days 127.0.0.1:1514->514/tcp harbor-log
[root@docker ~]#
查看客户端
[root@remote ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@remote ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
[root@remote ~]#
所谓Docker remote( 远程调用) api访问控制便是在不使用ssh链接目标端的方式去查看目标端的容器状态
关闭核心防护
[root@docker ~]# setenforce 0
setenforce: SELinux is disabled
6.2 修改配置文件docker.service
修改第14行参数
-H 指定协议
[root@docker ~]# vim /usr/lib/systemd/system/docker.service
14 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H unix:///var/run/docker.sock -Htcp://192.168.247.20:2375
6.3 重启服务
[root@docker ~]# systemctl daemon-reload
[root@docker ~]# systemctl restart docker
[root@docker ~]# netstat -natp | grep 2375
tcp 0 0 192.168.247.20:2375 0.0.0.0:* LISTEN 9905/dockerd
6.4 开放端口
[root@docker ~]# firewall-cmd --get-active-zones
public
interfaces: eth0 eth1
[root@docker ~]# firewall-cmd --zone=public --add-port=2375/tcp
success
6.5 使用remote节点去测试docker,成功
备注:使用本地测试的话,指定127.0.0.1
[root@remote ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
[root@remote ~]# docker -H tcp://192.168.247.20:2375 ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
94630e81bb21 vmware/harbor-jobservice:v1.2.2 "/harbor/harbor_jobs…" 2 days ago Exited (2) 3 minutes ago harbor-jobservice
e68e275ba6c5 vmware/nginx-photon:1.11.13 "nginx -g 'daemon of…" 2 days ago Exited (128) 3 minutes ago 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp, 0.0.0.0:4443->4443/tcp nginx
278c281594c9 vmware/harbor-ui:v1.2.2 "/harbor/harbor_ui" 2 days ago Up 29 seconds harbor-ui
b7adea7dfc28 vmware/registry:2.6.2-photon "/entrypoint.sh serv…" 2 days ago Exited (2) 3 minutes ago 5000/tcp registry
b587a5b5a4f9 vmware/harbor-db:v1.2.2 "docker-entrypoint.s…" 2 days ago Exited (128) 3 minutes ago 3306/tcp harbor-db
8fbb66df3206 vmware/harbor-adminserver:v1.2.2 "/harbor/harbor_admi…" 2 days ago Exited (2) 3 minutes ago harbor-adminserver
b282d0c45952 vmware/harbor-log:v1.2.2 "/bin/sh -c 'crond &…" 2 days ago Up 3 minutes 127.0.0.1:1514->514/tcp harbor-log
[root@remote ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@remote ~]#
6.6 测试拉取镜像
[root@remote ~]# docker -H tcp://192.168.247.20:2375 pull nginx
Using default tag: latest
[root@remote ~]# docker -H tcp://192.168.247.20:2375 images | grep nginx
nginx latest 602e111c06b6 2 days ago 127MB
compose_nginx_nginx latest e3abfd076454 4 days ago 726MB
vmware/nginx-photon 1.11.13 6cc5c831fc7f 2 years ago 144MB
到docker终端验证查看
[root@docker ~]# docker images | grep nginx
nginx latest 602e111c06b6 2 days ago 127MB
compose_nginx_nginx latest e3abfd076454 4 days ago 726MB
vmware/nginx-photon 1.11.13 6cc5c831fc7f 2 years ago 144MB
6.7 测试开启容器
[root@remote ~]# docker -H tcp://192.168.247.20:2375 run -itd --name gsycs nginx /bin/bash
f08182d315e6da8a43953695b72350302ba2d01e8d4cbf9fbeee7f8864e1468c
[root@remote ~]# docker -H tcp://192.168.247.20:2375 ps -a | grep gsycs
f08182d315e6 nginx "/bin/bash" 10 seconds ago Up 11 seconds 80/tcp
[root@docker ~]# docker ps -a | grep gsy
f08182d315e6 nginx "/bin/bash" 48 seconds ago Up 48 seconds 80/tcp gsycs
[root@docker ~]#
6.8 若是反馈无法连接,需要清空doker节点的iptables规则然后指定
error durin connect: Get http://192.168.247.20:2375/v1.40/containers/json:dial tcp 192.168.247.20:2375: connect: no route to host
[root@docker ~]# iptables -L;iptables -F
七:限制流量流向
使用防火墙过滤限制docker容器的源IP地址与外界通讯
[root@docker ~]# firewall-cmd --permanent --zone=public --add-rich-rule="rule family="ipv4" source address="192.168.247.0/24" reject"
[root@docker ~]# firewall-cmd --reload
大量问题的产生是因为Docker容器端口外放引起的漏洞,除了操作系统账户权限控制上的问题,更在于对Docker Daemon的进程管理上存在隐患
目前常用的Docker版本都支持Docker Daemon 管理宿主iptables,而且一旦启动进程上加上-p host_port:容器_port的端口映射,Docker Daemon会直接增加对应的forward chain并且-j ACCEPT;而默认的Drop规则实在INPUT链做,对docker无法限制,这边留下了很严重的安全隐患
因此建议如下:
1.不在有外网IP的主机上使用Docker服务
2.使用K8s等docker编排系统管理Docker容器
3.宿主上docker daemon启动命令加上一个–iptables=false,然后把常用iptables写进文件里,使用iptables-restore去执行
八:镜像安全
docker镜像安全扫描,在镜像仓库客户端使用证书认证,对下载的镜像进行检查
通过CVE数据库同步扫描镜像,一旦发现漏洞则通知用户处理,或者直接组织镜像继续构建
如果公司使用自己的镜像,可以跳过此步;否则,至少需要验证baseimage的md5等(哈希)特征值,确认一致后再基于baseimage进一步构建
一般来说,要确保只从受信任的库中获取镜像,并且不建议使用–insecure-registry=[]参数
推荐使用harbor私有仓库
九:Docker-TLS加密通讯
为了防止链路劫持、会话劫持等问题导致Docker通信时被中间人攻击,cs两端应该通过加密方式通讯
做TLS加密要保持环境的纯净,docker内没有镜像和容器
防止做了TLS后,还是有没有加密的数据传输
CA认证,确保发出去的消息进行加密,保持自己身份的唯一性
9.1 修改hosts文件
[root@ct ~]# vim /etc/hosts
127.0.0.1 ct
192.168.247.20 ct
192.168.247.142 gsy
[root@localhost ~]# vim /etc/hosts
192.168.247.20 ct
9.2 准备制作CA证书
[root@ct ~]# mkdir TLS
[root@ct ~]# cd ~/TLS/
[root@ct TLS]# ls
[root@ct TLS]#
9.3 创建CA密钥
备注:密码设为123123
rsa,非对称密钥,位数256位,-out 输出密钥文件ca-key.pem
[root@ct TLS]# openssl genrsa -aes256 -out ca-key.pem 4096
Generating RSA private key, 4096 bit long modulus
................................................................................................................................................................++
..................................................................................................................................................................++
e is 65537 (0x10001)
Enter pass phrase for ca-key.pem:
Verifying - Enter pass phrase for ca-key.pem:
[root@ct TLS]# ls
ca-key.pem
[root@ct TLS]#
这个只是一个原材料,接下来就用它创建CA证数
9.4 基于CA密钥创建CA证书
pem 证书
-subj 项目名称
-new 新请求。
-x509 输出一个x509结构,而不是cert. req。
-days 由-x509生成的证书的有效天数。
[root@ct TLS]# openssl req -new -x509 -days 1000 -key ca-key.pem -sha256 -subj "/CN=*" -out ca.pem
Enter pass phrase for ca-key.pem:此处输入ca-key.pem密码
You have new mail in /var/spool/mail/root
[root@ct TLS]# ls
ca-key.pem ca.pem
[root@ct TLS]#
9.5 创建ct节点证书
CA证书只是一个官方认证的证证书
接下来要创建ct、localhost的证书
此时创建ct的证书是有三步
1.设置私钥 确保安全加密
2.私钥签名 确保身份真实不可抵赖
3.制作证书
csr是一个签名文件
[root@ct TLS]# openssl genrsa -out ct-key.pem 4096 #创建服务器密钥
Generating RSA private key, 4096 bit long modulus
........................................................................................................++
...........................................................................................++
e is 65537 (0x10001)
You have new mail in /var/spool/mail/root
[root@ct TLS]# ls
ca-key.pem ca.pem ct-key.pem
[root@ct TLS]# openssl req -subj "/CN=*" -sha256 -new -key ct-key.pem -out ct.csr #签名私钥,csr是一个签名文件
[root@ct TLS]# ls
ca-key.pem ca.pem ct.csr ct-key.pem
[root@ct TLS]# openssl x509 -req -days 1000 -sha256 -in ct.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out ct-cert.pem
#//使用ca证书与私钥证书签名,导入签名ct.csr,指定CA文件和密钥文件,确定官方授权输入123123
Signature ok
subject=/CN=*
Getting CA Private Key
Enter pass phrase for ca-key.pem:
[root@ct TLS]# ls
ca-key.pem ca.pem ca.srl ct-cert.pem ct.csr ct-key.pem
9.6 同理生成localhost节点密钥
生成local密钥
[root@ct TLS]# openssl genrsa -out local-key.pem 4096
Generating RSA private key, 4096 bit long modulus
...............................................................................................++
.....................................................................................................++
e is 65537 (0x10001)
创建签名文件
[root@ct TLS]# openssl req -subj "/CN=client" -new -key local-key.pem -out local.csr
[root@ct TLS]# ls
ca-key.pem ca.pem ca.srl ct-cert.pem ct.csr ct-key.pem local.csr local-key.pem
创建配置文件,指定扩展密钥用途
[root@ct TLS]# echo extendedKeyUsage=clientAuth > extfile.cnf
签名证书
[root@ct TLS]# openssl x509 -req -days 1000 -sha256 -in local.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out local-cert.pem -extfile extfile.cnf
Signature ok
subject=/CN=client
Getting CA Private Key
Enter pass phrase for ca-key.pem:
查看当前文件
root@ct TLS]# ls
ca-key.pem ca.pem ca.srl ct-cert.pem ct.csr ct-key.pem extfile.cnf local-cert.pem local.csr local-key.pem
9.7 删除不需要的文件
删除签名文件,配置文件
[root@ct TLS]# rm -rf ca.srl ct.csr extfile.cnf local.csr
[root@ct TLS]# ls
ca-key.pem ca.pem ct-cert.pem ct-key.pem local-cert.pem local-key.pem
9.8 ct节点配置docker.service
新增指定 --tlsverify
–tlscacert=/root/TLS/ca.pem
–tlscert=/root/TLS/ct-cert.pem
–tlskey=/root/TLS/ct-key.pem
-H tcp://0.0.0.0:2376
-H unix:///var/run/docker.sock
[root@ct TLS]# vim /usr/lib/systemd/system/docker.service
14 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --tlsverify --tlscacert=/root/TLS/ca.pem --tlscert=/root/TLS/ct-cert.pem --tlskey=/root/TLS/ct-key.pem -H tcp://0.0.0.0:2376 -H unix:///var/run/docker.sock
[root@ct TLS]# systemctl daemon-reload
[root@ct TLS]# systemctl restart docker
[root@ct TLS]# netstat -natp | grep docker
tcp6 0 0 :::2376 :::* LISTEN 55402/dockerd
[root@ct TLS]# setenforce 0
setenforce: SELinux is disabled
本地验证
[root@ct TLS]# docker --tlsverify --tlscacert=ca.pem --tlskey=ct-key.pem --tlscert=ct-cert.pem -H tcp://ct:2376 images
REPOSITORY TAG IMAGE ID CREATED SIZE
systemctl new a2c3616f15d1 5 days ago 717MB
9.9 scp将local节点所需文件scp过去
[root@ct TLS]# scp ca.pem root@192.168.247.142:/etc/docker
root@192.168.247.142's password:
ca.pem 100% 1765 464.9KB/s 00:00
[root@ct TLS]# scp local* root@192.168.247.142:/etc/docker
root@192.168.247.142's password:
local-cert.pem 100% 1696 275.4KB/s 00:00
local-key.pem 100% 3243 989.6KB/s 00:00
[root@ct TLS]#
9.10 local节点指定加密文件远程调用测试
[root@localhost ~]# cd /etc/docker/
[root@localhost docker]# ls
ca.pem key.json local-cert.pem local-key.pem
[root@localhost docker]# docker --tlsverify --tlscacert=ca.pem --tlscert=local-cert.pem --tlskey=local-key.pem -H tcp://192.168.247.20:2376 ps
error during connect: Get https://192.168.247.20:2376/v1.40/containers/json: dial tcp 192.168.247.20:2376: connect: no route to host
出现报错,ct清空iptables
[root@ct TLS]# iptables -F
[root@ct TLS]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
systemctl new a2c3616f15d1 5 days ago 717MB
再次测试,出现如下报错
[root@localhost docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
[root@localhost docker]# docker --tlsverify --tlscacert=ca.pem --tlscert=local-cert.pem --tlskey=local-key.pem -H tcp://192.168.247.20:2376 ps
error during connect: Get https://192.168.247.20:2376/v1.40/containers/json: x509: cannot validate certificate for 192.168.247.20 because it doesn't contain any IP SANs
#获取https://192.168.247.20:2376/v1.40/containers/json: x509:无法验证192.168.247.20的证书,因为它不包含任何IP SANs
使用主机名可以正常访问
[root@localhost docker]# docker --tlsverify --tlscacert=ca.pem --tlscert=local-cert.pem --tlskey=local-key.pem -H tcp://ct:2376 ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@localhost docker]# docker --tlsverify --tlscacert=ca.pem --tlscert=local-cert.pem --tlskey=local-key.pem -H tcp://ct:2376 images
REPOSITORY TAG IMAGE ID CREATED SIZE
systemctl new a2c3616f15d1 5 days ago 717MB
十:dockerfile、compose创建容器注意要点
2016 年的 8 月 Github 上大量泄露个人或企业各种账号密码,出现这种问题一般都使用 dockerfile 或者 docker-compose 文件创建容器。
如果这些文件中存在账号密码等认证信息, 一旦 Docker 容器对外开放,则这些宿主机上的敏感信息也会随之泄露。
因此可以通过以下 方式检查容器创建模板的内容。
# check created users
grep authorized_keys $dockerfile
# check OS users
grep "etc/group" $dockerfile
# Check sudo users
grep "etc/sudoers.d" $dockerfile
# Check ssh key pair
grep ".ssh/.*id_rsa" $dockerfile
# Add your checks in below