Docker之Dockerfile
1 什么是Dockerfile
•Dockerfile其实就是根据特定的语法格式撰写出来的一个普通的文本文件,不用通过tar包迁移镜像,只用几KB的文件传递
•利用docker build命令依次执行在Dockerfile中定义的一系列命令,最终生成一个新的镜像(定制镜像)
1、对于开发人员:可以为开发团队提供一个完全一致的开发环境;
2、对于测试人员:可以直接拿开发时所构建的镜像或者通过Dockerfile文件构建一个新的镜像开始工作了;
3、对于运维人员:在部署时,可以实现应用的无缝移植。
2 Dockerfile 构建特征
•Dockerfile必须具备一个FROM命令来进行构建
•每一个Dockerfile命令都会构建一层镜像(本质上是每一层都会启动一个容器,执行完命令后,将容器进行提交后,产生新的镜像层)
•通过查看下载下来的镜像,发现历史层信息的层ID是missing,其实是因为原本的层id只存在于构建镜像的宿主机上,一旦转移镜像后,历史层消息中将只保留最新一层的ID
3 Dockerfile 命令概述
命令 | 作用 |
FROM image_name:tag | 定义了使用哪个基础镜像启动构建流程 |
MAINTAINER user_name | 声明镜像的创建者 |
ENV key value | 设置执行命令时的环境变量 (可以写多条),容器启动时就能拿到环境变量,如django项目mysql、redis的连接密码 |
RUN command | 构建镜像过程中需要执行的命令,是Dockerfile的核心部分(可以写多条) docker build |
ADD source_dir/file dest_dir/file | 将宿主机的文件复制到容器内,如果是一个压缩文件,将会在复制后自动解压 |
COPY source_dir/file dest_dir/file | 和ADD相似,但是如果有压缩文件并不能解压 |
WORKDIR path_dir | 设置工作目录,进入容器 /bin/bash或执行某个命令时在哪个路径下 |
CMD | 添加启动容器时需要执行的命令。多条只有最后一条生效。可以在启动容器时被覆盖和修改。 |
ENTRYPOINT | 同CMD,但这个一定会被执行,不会被覆盖修改。 |
EXPOSE | 设置对外暴露的端口,后期启动容器时可以-p做映射 |
ARG | 设置只在构建过程中使用的环境变量,构建完成后,将消失 |
VOLUME | 添加数据卷,后期启动容器时可以-v做映射 |
USER | 指定以哪个用户的名义执行RUN, CMD 和ENTRYPOINT等命令 |
ONBUILD | 如果制作的镜像被另一个Dockerfile使用,将在那里被执行Docekrfile命令 |
STOPSIGNAL | 设置容器退出时发出的关闭信号 |
HEALTHCHECK | 设置容器状态检查。 |
SHELL | 更改执行shell命令的程序。Linux的默认shell是[“/bin/sh”, “-c”],Windows的是[“cmd”, “/S”, “/C”] |
4 Dockerfile 示例与使用
4.1 Dockerfile参考示例
Dockerfile.txt文件配置
# django项目下创建一个requirements.txt,生成项目依赖数据,建一个Dockerfile.txt,建一个uwsgi.ini,都在项目内先配置好
# 项目push到git---> 服务器从git拉下来,在项目内就有requirements、Dockerfile、uwsgi.ini文件
# mkdir -p /opt/zl
# cd /opt/zl
# git clone ...django_docker...
# Dockerfile.txt 文件配置
FROM python:3.6
MAINTAINER zl
EXPOSE 8080 # 端口暴露,可以先不写,后面用 -p映射
ADD ./requirements.txt /project/ # 拷贝服务器当前路径下的requirements.txt到容器内
RUN pip install -r /project/requirements.txt -i https://pypi.douban.com/simple/ # 安装项目依赖
RUN pip install uwsgi -i https://pypi.douban.com/simple/ # 安装uwsgi
VOLUME ["/project"] # 目录开放,可以先不写,后面用 -v映射
WORKDIR /project/django_docker
# 运行容器时执行的命令,用uwsgi启动项目,指定uwsgi路径(工作路径就在项目根路径,不用指定了)
# uwsgi支持ini文件配置,路飞项目上线时,uwsgi是用xml文件配置的,启动命令是 uwsgi -x /project/luffyapi.xml
# CMD ["uwsgi", "--ini", "uwsgi.ini"]
# 用python命令启动项目
CMD ["python", "/project/django_docker/manage.py", "runserver", "0.0.0.0:8080"]
uwsgi.ini文件配置
[uwsgi]
# 配置和nginx连接的socket连接,不通过nginx访问不到,因为不能接收http请求,参数前加分号是注释
;socket=0.0.0.0:8080
# 使用http连接
http=0.0.0.0:8080
# 配置项目路径、项目所在目录
chdir=/project/django_test
# 配置wsgi接口模块文件路径,以项目根路径下的wsgi.py启动
wsgi-file=django_test/wsgi.py
# 配置启动的进程数
processes=4
# 配置每个进程的线程数
threads=2
# 配置启动管理主进程
master=True
# 配置存放主进程进程号的文件
pidfile=uwsgi.pid
# 配置dump日志记录,日志文件输出到这个文件,不会输出到控制台。
# daemonize以守护进程方式启,没有可以夯住的前台进程,这样启动uwsig项目不会运行。
# daemonize=uwsgi.log
4.2 Dockerfile使用命令构建镜像 – docker build
# 作用:
根据dockerfile创建镜像
# 命令格式:
docker build [OPTIONS] PATH | URL | -
# 命令参数:
PATH Dockerfile所在路径(文件夹路径),文件名必须是Dockerfile
URL Dockerfile所在URL地址
OPTIONS:
-t, --tag list 为镜像设置名称和tag
-f, --file string 指定Dockerfile的路径(这是可以使用其他名称命名Dockerfile)
# 命令演示:注意后边的空格和点,不要省略
# 通过dockerfile构建出镜像,点指定的是根据当前dockerfile构建, 'django2.0'是镜像名字
docker build -t='django2.1.3' .
4.3 基于自己构建的镜像启动容器
# /zl路径下是django_docker项目,直接把/zl映射到容器的/project
# 可以启多个容器,拉起多个django项目,监听不同端口,相当于在多个机器上运行多个django项目
docker run -di --name=mydjango2 -v /opt/zl/:/project -p 8080:8080 mydjango:v2
docker run -di --name=mydjango3 -v /opt/zl/:/project -p 8081:8080 mydjango:v2
docker run -di --name=mydjango4 -v /opt/zl/:/project -p 8082:8080 mydjango:v2
5 配置nginx转发
5.1 基于nginx转发
nginx可以跑在docker里,也可以跑在服务器上,下例以docker启动nginx
1 创建目录,nginx配置文件、静态页面、日志文件等要做目录映射mkdir -p /opt/nginx/conf /opt/nginx/html /opt/nginx/logs
2 新建配置文件vim nginx/conf/nginx.conf
3 nginx.conf
配置文件
worker_processes 1; # 起一个进程
events {
worker_connections 1024; # 最大连接数
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80; # nginx监听80端口
server_name localhost;
location / {
#方式一:
include uwsgi_params; #导入一个nginx模块,它是用来和uwsgi进行通讯的
uwsgi_connect_timeout 30; #设置uwsgi超时时间
uwsgi_pass 101.133.225.166:8080;
#方式二:
include uwsgi_params; #导入一个nginx模块,它是用来和uwsgi进行通讯的
uwsgi_pass unix://var/www/script/uwsgi.sock; #指定uwsgi的sock文件的所有动态请求
#方式三:只能转发http请求,直接通过nginx访问,因为django项目容器我们用python命令启动,没有用uwsgi启动,这里用方式三
proxy_pass http://101.133.225.166:8080;
}
error_page 500 502 503 504 /50x.html;
location= /50x.html{
root html;
}
}
}
4 docker 中运行nginx
docker run --name nginx -id -p 80:80 -v /opt/nginx/conf/nginx.conf:/etc/nginx/nginx.conf
-v /opt/nginx/html:/etc/nginx/html -v /opt/nginx/logs:/var/log/nginx nginx
5.2 基于nginx配置负载均衡
修改nginx.conf
配置文件
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream node {
server 101.133.225.166:8080;
server 101.133.225.166:8081;
server 101.133.225.166:8082;
}
server {
listen 80;
server_name localhost;
location / {
#负载均衡配置 按照http中node配置ip进行转发
proxy_pass http://node;
}
}
}
docker restart nginx
重启nginx
负载均衡后,假设8081的容器和8080的容器挂了,还有8082端口正常提供服务;运维发现docker挂了,再把docker容器启动起来即可,或者用镜像重新启容器也可以(因为做了目录映射)