Docker六脉神剑 (三) 编写Dockerfile构建nginx镜像并推送到远程仓库给其他人使用
在使用docker
中, 我们经常会使用到一些镜像, 但是往往我们使用的都是基础镜像。想要使用到一些工具, 只能再进入容器安装, 那能不能我们自定义镜像, 比方说 我默认拉一个镜像, 这个镜像默认就安装了nginx
, 或者默认已经安装了vim
?
因为镜像的里面有什么东西是利用Dockerfile
来声明的,也就是我们想要实现自定义功能我必须得懂Dockerfile
。
Dockerfile
实际上就是一个文本, 然后编写docker
可以认识的语法, 那么就可以构建我们想要的镜像。
Dockerfile构建Nginx镜像
FROM centos:centos7
# 从centos基础镜像构建
# 设置工作目录
WORKDIR "/tmp"
# 这里远程下载太慢了 我直接本地弄得。大家可以使用wget来进行远程下载
ADD nginx-1.17.5.tar.gz /tmp
# 添加nginx用户
RUN useradd -M -s /sbin/nologin nginx
# 安装相关依赖
RUN yum -y install gcc* make pcre-devel zlib-devel openssl openssl-devel libxslt-devel gd gd-devel GeoIP GeoIP-devel pcre pcre-devel
&& cd nginx-1.17.5
&& ./configure --user=nginx --group=nginx --prefix=/usr/local/nginx --with-file-aio --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_xslt_module --with-http_image_filter_module --with-http_geoip_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_auth_request_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_stub_status_module && make && make install
&& echo "hello aoppp.com" > /usr/local/nginx/html/index.html
# 表示对外期望暴露得端口
EXPOSE 80
# 启动nginx 将nginx主进程 pid为1 nginx一旦挂掉那么docker容器就会直接退出
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
然后我们将dockerfile
构建出来, 运行以下命令来使用nginx
镜像
docker build -f nginxDockerfile -t aoppp/nginx:v1 . # 指定dockerfile构建 提供上下文环境
docker run --name aoppp-nginx -d -p 80:80 aoppp/nginx:v1 # 后台启动一个容器 并进行端口映射
看看localhost
已经成功了
上传到docker hub
我们拉取的镜像默认都是从docker hub来的, 如果我们做的镜像想要被别人直接pull下来, 我们也需要上传到docker hub。docker hub地址
没有账号的要先创建账号呀,博主这边已经准备好了呀。
使用docker login
登录账号, 在docker hub上面创建我们需要上传的仓库
给创建好的镜像打上标签
# 这里 aoppp/nginx:v1本地镜像的名字 testsmile/aoppp:v1是重新启的名字 是和远程的要对上。
docker tag aoppp/nginx:v1 testsmile/aoppp:v1
docker push testsmile/aoppp:v1 # 推送至远程仓库
推送成功, 并且搜索一下呀!
从远程拉下来本地构建一下试试
docker pull testsmile/aoppp:v1
docker run --name aoppp-nginx -d -p 80:80 testsmile/aoppp:v1
访问localhost
这样就已经ok了
编写dockerfile需要注意
将多个RUN
指令合并为一个, 因为Docker
镜像是分层的
-
Dockerfile
中的每个指令都会创建一个新的镜像层。 - 镜像层将被缓存和复用
- 当
Dockerfile
的指令修改了,复制的文件变化了,或者构建镜像时指定的变量不同了,对应的镜像层缓存就会失效 - 某一层的镜像缓存失效之后,它之后的镜像层缓存都会失效
- 镜像层是不可变的,如果我们再某一层中添加一个文件,然后在下一层中删除它,则镜像中依然会包含该文件(只是这个文件在Docker容器中不可见了)。
-
Docker
镜像类似于洋葱。它们都有很多层。为了修改内层,则需要将外面的层都删掉。记住这一点的话,其他内容就很好理解了。
因此,我建议大家为每个应用构建单独的Docker
镜像,然后使用 Docker Compose
运行多个Docker
容器。
容器只运行单个应用
- 从技术角度讲,你可以在
Docker
容器中运行多个进程。你可以将数据库
,前端
,后端
,ssh
,supervisor
都运行在同一个Docker
容器中。但是,这会让你非常痛苦: - 非常长的构建时间(修改前端之后,整个后端也需要重新构建)
- 非常大的镜像大小
- 多个应用的日志难以处理(不能直接使用
stdout
,否则多个应用的日志会混合到一起) - 横向扩展时非常浪费资源(不同的应用需要运行的容器数并不相同)
- 僵尸进程问题 - 你需要选择合适的
init
进程
COPY与ADD优先使用前者 合理调整COPY与RUN的顺序
我们应该把变化最少的部分放在Dockerfile
的前面,这样可以充分利用镜像缓存。
选择合适的基础镜像(alpine版本最好)
alpine
是最精简的linux
编写.dockerignore文件
构建镜像时,Docker
需要先准备context
,将所有需要的文件收集到进程中。默认的context
包含Dockerfile
目录中的所有文件,但是实际上,我们并不需要.git
目录,node_modules
目录等内容。 .dockerignore
的作用和语法类似于 .gitignore
,可以忽略一些不需要的文件,这样可以有效加快镜像构建时间,同时减少Docker
镜像的大小。示例如下:
.git/
node_modules/
快去看看其他文章!!!!!!! ??
本文为作者原创,手码不易,允许转载,转载后请以链接形式说明文章出处。
- Python进阶02 文本文件的输入输出
- Python进阶01 词典
- 微信公布上线小程序游戏 腾讯应用宝安卓平台首发
- Python基础10 反过头来看看
- CCCF 微软沈向洋:理解自然语言:表述、对话和意境
- Linux进程基础
- Android Studio导入项目非常慢的解决办法
- Android开发中遇到的requestFeature() must be called before adding content异常
- Linux信号基础
- 剑指OFFER之合并有序链表(九度OJ1519)
- Android Studio快捷键每日一练(6)
- Linux文本流
- Linux并发与同步
- Android Studio快捷键每日一练(5)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 一次排查线上接口偶发异常耗时引起的思考!
- 台阶很高,青蛙跳不跳?
- 从零开始认识堆排序
- Redis SDS 深入一点,看到更多!
- Centos7下Oracle 11g r2 本地/远程 用exp/imp命令快速导入导出数据 实践笔记
- js常用函数大全107个
- xtraReprot 动态绑定数据 数据列动态
- 线上问题分析之java dump文件生成
- python基础知识
- AtCoder Beginner Contest 177 A ~ E
- 2017 年ICPC 中国大陆区域赛铜牌题解
- 搜索(DFS BFS)专题练习
- AtCoder Beginner Contest 171
- AtCoder Beginner Contest 173 A ~ F(已经补完)
- AtCoder Beginner Contest 174 A ~ E