Dockerfile+harbor私服
一 docker工作流
1. docker管理流程
2. 镜像仓库阿里
(1) 阿里私有仓库
公司内部管理项目涉及到的所有docker镜像,会使用私有仓库的方式,集中管理。
(2) 创建阿里Docker仓库
-
登录阿里云创建私有仓库
对仓库进行配置
-
创建命名空间
通常一个项目,包含了多个镜像,为了方便管理,将多个同属于一个项目的所有镜像放在一个命名空间中。
命名规范:公司名_项目名
-
创建镜像仓库
一个仓库管理一个镜像的多个版本,一个镜像的多个版本。
命名规范:服务名_v1.0:tag
(3) 案例:nginx镜像推送
1. 拉取nginx基础镜像
docker pull nginx:1.21
2. 启动容器
docker run --name nginx-10 -d -p 88:80 nginx:1.21
注意:打包容器,开启新容器,将需要打包文件使用docker cp拷贝进去。无法打包容器卷中数据。
3. 部署代码
将代码docker cp拷贝到容器中。
4. 提交镜像
docker commit -a "yangdd@zparkhr.com.cn" -m "第一个版本cms前端代码" nginx-10 cms_nginx:1.1
5. 登录阿里云镜像
docker login --username=15533349688 registry.cn-zhangjiakou.aliyuncs.com
说明:
--username:阿里云仓库注册的手机号。
6. 给镜像打tag
docker tag cms_nginx:1.1 registry.cn-zhangjiakou.aliyuncs.com/zxtec_cms/cms_nginx:0.1
注意:镜像最后的名字要和阿里云仓库名一致
7. 推送镜像
docker push registry.cn-zhangjiakou.aliyuncs.com/zxtec_cms/cms_nginx:0.1
(4) 案例:拉取部署镜像
1. 从阿里私服中拉取镜像
docker pull registry.cn-zhangjiakou.aliyuncs.com/zxtec_cms/cms_nginx:0.1
2. 启动容器
docker run --name cms-nginx -d -p 80:80 -v app_nginx_html:/usr/share/nginx/html -v app_nginx_conf:/etc/nginx/conf.d -v app_nginx_logs:/var/log/nginx registry.cn-zhangjiakou.aliyuncs.com/zxtec_cms/cms_nginx:1.0
3. 测试验证
二 DockerFile
1. 简介
(1) 场景
自定义构建镜像,如果使用docker commit,优缺点
- ① commit打包过程,对操作者不可见,不知道内部打包了什么,做了什么,有什么问题。
- ② 所有容器的改动,需要手工操作,不具备可复制性,不具备自动化,不具备规模性。
(2) DockerFile简介
一种脚本语言,用来描述Docker镜像构建过程,也就是一个说明书,Docker通过dockerfile构建出来一个自定义镜像。
(3) Dockerfile作用
通过使用Dockerfile,开发人员可以通过简单的文本文件定义和管理镜像的构建过程,实现自动化、可重复和可管理的镜像构建。
-
自动化构建:
通过编写Dockerfile,可以自动构建Docker镜像,而无需手动逐步执行构建步骤。Docker根据Dockerfile中的指令顺序执行构建步骤,从而实现自动化构建过程。
效率高,便于管理,便于和其他平台集成。 -
版本控制:
Dockerfile本身是一个文本文件,通过对Dockerfile内容版本控制,也就实现了Image镜像的版本控制管理。
(4) 指令
指令 | 作用 |
---|---|
FROM | 基础镜像,从这个镜像开始制作 |
LABEL | 描述,描述镜像的信息:作者、文字描述、日期、要求数据卷路径 (没有任何docker构建的作用,仅仅给工作人员看的 ) |
maintainer | 描述信息,写作者信息。作用类似label。逐渐被废弃。 |
RUN | 在构建镜像的时候,执行一些命令的。 |
ADD | 向镜像中拷贝文件 |
COPY | 向镜像中拷贝文件 |
VOLUME | 数据卷目录,指定镜像中的那个目录,作为日后数据卷挂载目录。(不写也能挂载,给工作人看的 ) |
EXPOSE | 暴露开放容器端口 |
ENV | 定义环境变量 |
WORKDIR | 工作目录,就是exec进入容器,默认初始位置。 |
ONBUILD | 当构建一个被继承 Dcokerfile 这个时候就会触发运行ONBUILD命令–了解。 |
CMD | 在容器启动的时候,会执行的命令。 |
entrypoint | 在容器启动的时候,会执行的命令,例如:redis镜像,一定有redis-server ./redis.conf |
2. 第一个案例
构建一个自定义的tomcat镜像,基于tomcat:8.5构建。
(1) 创建dockerfile文件
例如:dockerfile/tomcat/dockerfile-tomcat-1.0
注意:dockerfile到一定要放在一个单独的目录中。
命令:
touch dockerfile-tomcat-1.0
(2) 编写dockerfile指令
# 基础镜像
FROM tomcat:8.5
# 描述
LABEL name="yangdd@zparkhr.com.cn"
LABEL desc="这是一个dockerfile构建的tomcat镜像"
(3) 构建镜像
1. 语法
docker build -t 镜像名:tag -f dockerfile的文件名 .
2. 命令
docker build -t my-tomcat:1.0 -f dockerfile-tomcat-1.0 .
(4) 验证
查看镜像信息
docker inspect 镜像名:tag
3. 详解指令
(1) FROM
基础镜像,本次docker镜像的构建基于From镜像基础之上进行操作。
-
语法
FROM <image>:<tag>
-
说明
FROM
必须是Dockerfile文件的第一行指令。- 用于为镜像文件构建过程指定基础镜像,后续的指令都基于该基础镜像环境运行
- 基础镜像可以是任何一个镜像文件
(2) LABEL
镜像描述信息,描述镜像的信息:作者、文字描述、日期、要求数据卷路径,(没有任何docker构建的作用,
仅仅给工作人员看的
)
-
语法
# 形式1: LABEL author="fanqingfuming@zparkhr.com.cn" LABEL desc="这是描述" # 形式2: LABEL name="反清复明" age="18" desc="这是一段image描述"
-
说明
LABEL
指令用来给镜像以name=value对的形式添加一些描述信息- 会集成基础镜像中的
LABEL
属性,通过docker inspect
,name不能重复,如果value相同会被覆盖
(3) COPY
从主机(执行docker build)中,拷贝文件或者目录到镜像里面。主机路径?
-
语法
COPY <主机src> <镜像dest>
-
说明
<src>
:要复制的源文件或目录,支持通配符<src>
必须在build所在路径或子路径下,不能是其父目录<dest>
:目标路径,即镜像中文件系统的路径<dest>
目录结尾必须以/结尾。
-
案例
FROM centos:7 LABEL name="反清复明" age="18" desc="这是一段image描述" COPY C.txt /opt/cpdir/ COPY dir/* /opt/cpdir/dir/
(4) ADD
类似COPY,但ADD支持tar包自解压和网络路径。
-
语法
ADD <src> <dest>
-
说明
<src>
可以是一个文件,可以是一个目录,也可以是一个网络url路径。<src>
如果是一个压缩文件(tar),被被解压为一个目录,如果是通过URL下载一个文件不会被解压<dest>
必须以/结尾。
-
案例
FROM centos:7 LABEL name="反清复明" age="18" desc="这是一段image描述" COPY C.txt /opt/cpdir/ COPY dir/* /opt/cpdir/dir/ ADD dir/* /opt/adddir/dir/ ADD https://www.cnblogs.com/azulearncode/p/14043606.html /opt/adddir/ ADD ./jdk-8u291-linux-x64.tar.gz /opt/adddir/dir/
(5) ENV
设置镜像中的环境变量,这个变量可以在镜像中直接使用,也可以给会在镜像中执行的命令使用,后续的dockerfile指令使用。
-
语法
- 定义环境变量
# 一次设置一个 ENV <key>=<value> # 一次设置多个 ENV <key>=<value> <key1>=<value1> <key2>=<value2> .....
- 使用环境变量
$key ${key}
-
说明
- 可以用来定义镜像使用的环境变量
- 也可以为后续的指令,定义shell变量。
-
案例
FROM centos:7 LABEL name="反清复明" age="18" desc="这是一段image描述" COPY C.txt /opt/cpdir/ COPY dir/* /opt/cpdir/dir/ ADD dir/* /opt/adddir/dir/ ADD https://www.cnblogs.com/azulearncode/p/14043606.html /opt/adddir/ ADD ./jdk-8u291-linux-x64.tar.gz /opt/adddir/dir/ ENV PATH=$PATH:/opt/adddir/dir/jdk1.8.0_291/bin ENV JAVA_HOME=/opt/adddir/dir/jdk1.8.0_291
(6) WORKDIR
指定创建容器后,终端进入容器后的默认路径,后续的RUN、CMD、ENTRYPOINT、COPY、ADD涉及到的路径,均以此目录作为当前目录。
-
语法
WORKDIR /opt/centos
-
说明
- 如果设置的目录不存在会自动创建,包括他的父目录
- 如果使用相对路径,则相对workdir的路径
WORKDIR
也可以调用ENV指定的变量
-
案例
FROM centos:7 LABEL name="反清复明" age="18" desc="这是一段image描述" COPY C.txt /opt/cpdir/ COPY dir/* /opt/cpdir/dir/ ADD dir/* /opt/adddir/dir/ ADD https://www.cnblogs.com/azulearncode/p/14043606.html /opt/adddir/ ADD ./jdk-8u291-linux-x64.tar.gz /opt/adddir/dir/ ENV PATH=$PATH:/opt/adddir/dir/jdk1.8.0_291/bin ENV JAVA_HOME=/opt/adddir/dir/jdk1.8.0_291 WORKDIR ${JAVA_HOME}
(7) RUN
构建**
镜像
**过程中,需要执行的命令,可以用来安装依赖,初始化脚本执行等。
-
语法
# 语法1,shell 形式 RUN command1 && command2 RUN yum install -y vim && yum install -y wget # 语法2,exec 形式 RUN ["executable","param1","[param2]"] RUN ["yum","install","-y","vim"] RUN ["yum","install","-y","wget"]
-
说明
RUN
在下一次建构期间,会优先查找本地缓存,若不想使用缓存可以通过docker build --no-cache
解除RUN
指令指定的命令是否可以执行取决于 基础镜像中是否允许执行该命令。- shell形式,可以使用
&&
或\
连接多个命令 - 一个run就会构建一层镜像,尽量减少run个数。如果命令多,尽量使用&&连接。
exec
形式,必须使用"“,且第一个命令必须独立是一个命令,后面可以是参数,每个参数独立放在一个”"中。- 与 shell 形式不同,exec 形式不会调用shell解析。例如
RUN ["echo","$HOME"]
;这样的指令$HOME
并不会被解析。
-
案例
FROM centos:7 LABEL name="反清复明" age="18" desc="这是一段image描述" COPY C.txt /opt/cpdir/ COPY dir/* /opt/cpdir/dir/ ADD dir/* /opt/adddir/dir/ ADD https://www.cnblogs.com/azulearncode/p/14043606.html /opt/adddir/ ADD ./jdk-8u291-linux-x64.tar.gz /opt/adddir/dir/ ENV PATH=$PATH:/opt/adddir/dir/jdk1.8.0_291/bin ENV JAVA_HOME=/opt/adddir/dir/jdk1.8.0_291 WORKDIR ${JAVA_HOME} RUN ["java","-version"] RUN echo "哈哈" && echo $(date) RUN ["/bin/sh","-c","echo $HOME"]
(8) EXPOSE
为镜像设置日后启动容器暴露的端口。
-
语法
EXPOSE <port> EXPOSE <port>/<protocol> EXPOSE 80 EXPOSE 80/tcp EXPOSE 2379/udp
-
说明
<port>
:端口号<protocol>
:协议类型,默认TCP协议,tcp/udp/- 并不会直接暴露出去,docker run时还需要-P指定才可以,这里就是一个说明,
给镜像使用者看的
。
-
案例
FROM centos:7 LABEL name="反清复明" age="18" desc="这是一段image描述" COPY C.txt /opt/cpdir/ COPY dir/* /opt/cpdir/dir/ ADD dir/* /opt/adddir/dir/ ADD https://www.cnblogs.com/azulearncode/p/14043606.html /opt/adddir/ ADD ./jdk-8u291-linux-x64.tar.gz /opt/adddir/dir/ ENV PATH=$PATH:/opt/adddir/dir/jdk1.8.0_291/bin ENV JAVA_HOME=/opt/adddir/dir/jdk1.8.0_291 WORKDIR ${JAVA_HOME} RUN ["java","-version"] RUN echo "哈哈" && echo $(date) RUN ["/bin/sh","-c","echo $HOME"] EXPOSE 80/udp EXPOSE 6379/tcp
(9) VOLUME
说明数据挂载目录,希望将宿主机目录挂载到容器中,但是不声明也可以挂载,所以该指令仅
仅是给镜像使用者查看
使用。
-
语法
VOLUME ["/data","/opt/data","/var/logs"]
-
说明
- 目录必须存在,不存在则声明失败。
- 一般不需要在Dockerfile中写明,且在Kubernetes场景几乎没用
-
案例
FROM centos:7 LABEL name="反清复明" age="18" desc="这是一段image描述" COPY C.txt /opt/cpdir/ COPY dir/* /opt/cpdir/dir/ ADD dir/* /opt/adddir/dir/ ADD https://www.cnblogs.com/azulearncode/p/14043606.html /opt/adddir/ ADD ./jdk-8u291-linux-x64.tar.gz /opt/adddir/dir/ ENV PATH=$PATH:/opt/adddir/dir/jdk1.8.0_291/bin ENV JAVA_HOME=/opt/adddir/dir/jdk1.8.0_291 WORKDIR ${JAVA_HOME} RUN ["java","-version"] RUN echo "哈哈" && echo $(date) RUN ["/bin/sh","-c","echo $HOME"] EXPOSE 80/udp EXPOSE 6379/tcp VOLUME ["/opt/data","/var/log"]
(10) ENTRYPOINT和CMD
为容器设定,启动容器时,默认执行一次的命令,主要用于指定启动容器的前台进程,例如:redis容器启动默认执行:
redis-server
-
语法
- ENTRYPOINT语法
# 语法,exec形式 --推荐 ENTRYPOINT ["命令","param1","param2"]
- CMD语法
# 语法1,exec形式--推荐 CMD ["executable","param1","param2"] # 语法2,还是exec形式,不过仅设置参数,结合entrypoint使用。--推荐 CMD ["param1","param2"]
-
说明
- 一个Dockerfile中可以有多个
ENTRYPOINT
或者CMD
,但只有最后一个生效 CMD
如果结合entrypoint使用,通常用来指定参数(ENTRYPOINT 负责命令以及不可变参数,CMD 负责可变参数),且参数可以被docker run 镜像后面的命令替换CMD的参数。ENTRYPOINT
主要用于服务器程序启动命令。
- 一个Dockerfile中可以有多个
-
案例
FROM centos:7 LABEL name="反清复明" age="18" desc="这是一段image描述" COPY C.txt /opt/cpdir/ COPY dir/* /opt/cpdir/dir/ ADD dir/* /opt/adddir/dir/ ADD https://www.cnblogs.com/azulearncode/p/14043606.html /opt/adddir/ # ADD ./jdk-8u291-linux-x64.tar.gz /opt/adddir/dir/ # ENV PATH=$PATH:/opt/adddir/dir/jdk1.8.0_291/bin # ENV JAVA_HOME=/opt/adddir/dir/jdk1.8.0_291 # WORKDIR ${JAVA_HOME} # RUN ["java","-version"] RUN echo "哈哈" && echo $(date) RUN ["/bin/sh","-c","echo $HOME"] EXPOSE 80/udp EXPOSE 6379/tcp VOLUME ["/opt/data","/var/log"] ENTRYPOINT [ "ping","-c","5"] CMD [ "www.baidu.com" ]
-
测试
替换cmd参数 [root@localhost docker]# docker run --name c8 -d centos7:0.1 www.sohu.com
3. 案例
java程序开发了java项目,文件:
app.jar
,将部署jdk环境的镜像中。启动java项目:
java -jar app.jar --spring.config.location=application.properties
-
(1) 启动mysql容器
docker run --name app-mysql -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=admins mysql:5.7
-
(2) 编写springboot项目dockerfile
# 基础jdk FROM openjdk:8-jre # 设置workdir,路径设置为app.jar所在路径 WORKDIR ${app_path} # 端口暴露 EXPOSE 8080/tcp # 拷贝项目相关文件到 /opt/app/ ENV app_path=/opt/app/ COPY application.properties ${app_path} COPY app.jar ${app_path} # 容器启动,启动app.jar ENTRYPOINT ["java","-jar","app.jar"] CMD ["--spring.config.location=application.properties"]
注意:1. workdir放在前面,2. entrypoint存放不变命令,cmd存放可变参数
例如:
- application-dev.properties:开发配置文件。
- application-test.properties:测试配置文件
- application.properties:上线配置文件
-
(3) 构建镜像
docker build --no-cache -t app-server:0.1 -f dockerfile .
-
(4) 启动容器
docker run ...
三 Harbor私服
1. 场景
在实际生产运维中,往往需要把镜像发布到几十、上百台或更多的节点上。这时单台Docker主机上镜像已无法满足,项目越来越多,镜像就越来越多,都放到一台Docker主机上是不行的。需要一个仓库统一管理镜像。
2. 引言
Harbor英文港口的意思,Docker镜像是一个鲸鱼拖着集装箱,寓意:用来管理停靠 Docker镜像
Habor是由VMWare公司开源的容器镜像仓库Registry(Docker-Hub)。 Harbor是一个用于存储和分发Docker镜像的企业级Registry服务器,由VMware开源。
3. 功能
(1) 基于角色访问控制
在企业中,通常有不同的开发团队负责不同的项目,镜像像代码一样,每个人角色不同需求也不同,因此就需要访问权限控制,根据角色分配相应的权限。
例如,开发人员需要对项目构建这就用到读写权限(push/pull),测试人员只需要读权限(pull),运维一般管理镜像仓库,具备权限分配能力,项目经理具有所有权限。
(2) 图形化界面
用户可以通过浏览器查看、检索当前Docker镜像仓库,并可进行管理项目和命名空间的操作;
(3) 镜像删除和空间回收
Harbor支持在Web删除镜像,回收无用的镜像,释放磁盘空间。
(4) 安全审计
所有针对镜像仓库的操作都可以被记录追溯,用于审计管理;
(5) REST API
可以通过java代码实现内部功能管理。完整的API,方便与外部集成。
(6) 部署简单
harbor安装部署简单。
4. 安装要求
(1) 硬件要求
资源 | 最小要求 | 推荐配置 |
---|---|---|
CPU | 2 CPU | 4 CPU |
Mem | 4 GB | 8 GB |
Disk | 40 GB | 160 GB |
(2) 软件要求
软件 | 版本号 |
---|---|
docker | 17.06.0 及以上 |
docker-compose | 1.18.0 及以上 |
openssl |
(3) 网络端口要求
端口 | 协议 | 描述 |
---|---|---|
443 | https | https端口,可以从配置文件中修改 |
4443 | https | 当notary打开时使用,否则不需要使用,可以通过配置文件修改 |
80 | http | http端口,可以从配置文件中修改 |
5. 安装
(1) 安装docker
(2) 安装docker-compose
1. 安装扩展yum源
yum install -y epel-release
yum makecache fast
2. 安装docker-compose
yum install -y docker-compose
3. 验证docker-compose
[root@localhost ~]# docker-compose -v
docker-compose version 1.18.0, build 8dd22a9
(3) 离线安装解压harbor
tar zxvf harbor-offline-installer-v2.5.3.tgz -C /opt/installs/
(4) 修改配置 harbor.yml
前提:将harbor.yml.tmpl文件改为harbor.yml
(5) 初始化配置
1. 修改harbor的域名或者ip
hostname: 192.168.127.100
2. 网络连接harbor使用http协议端口
http:
port: 99
3. 如果不使用https,注释掉
# https:
# # https port for harbor, default is 443
# port: 443
# # The path of cert and key files for nginx
# certificate: /your/certificate/path
# private_key: /your/private/key/path
4. 登录harbor的超级管理员密码
harbor_admin_password: *******
(6) 安装
./install.sh
(7) 检验
查看所有harbor程序
docker-compose ps
(8) 故障处理
如果有容器的状态不是up运行状态,查看harbor日志
/var/log/harbor
(9) 访问
1. 地址
http://harbor的ip:99
2. 超级管理员登录
用户名:admin
密码:配置的密码
6. docker绑定
(1) 修改/etc/docker/daemon.json
{
"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"],
"insecure-registries": ["192.168.199.51:88"] /*harbor的ip:端口*/
}
(2) 重启docker引擎
systemctl daemon-reload
systemctl restart docker
(3) 使用docker-compose重启harbor所有容器
注意:必须在harbor解压文件夹下面,docker-compose.yml文件位置。执行命令。
1. 关闭
docker-compose down -v
2. 启动
docker-compose up -d
7. 项目和角色
登录harbor操作
8. push推送镜像
假设有app-server和mysql两个镜像,属于cms项目,推送镜像成品。
(1) 给镜像打上tag(harbor)
命令:`docker tag 镜像名:tag harbor的ip:端口/项目名/镜像名:tag`
```shell
1. 给app-server:1.0打标签
2. 给mysql:5.7打标签
(2) 登录私服
命令:docker login harbor的ip:端口
[root@localhost harbor]# docker login 192.168.127.100:99
Username: admin
Password:
(3) 推送镜像
命令:docker push 带harbor前缀的镜像:tag
1. 推送app-server
[root@localhost harbor]# docker push 192.168.127.100:99/cms/app-server:1.0
2. 推送mysql
[root@localhost harbor]# docker push 192.168.127.100:99/cms/mysql:5.7-1
9. pull拉取镜像
docker pull 192.168.127.100:99/cms/mysql:5.7-1