在使用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/
快去看看其他文章!!!!!!! 😠😠