Django应用容器化

Published on with 0 views and 0 comments

Docker

三大核心要素:镜像(Image)、容器(Container)、仓库(Registry)

(先整体看下流程,再逐个演示)

镜像(Image)

打包了业务代码及运行环境的包,是静态的文件,不能直接对外提供服务。

容器(Container)

镜像的运行时,可以对外提供服务。本质上讲是利用 namespace 和 cgroup 等技术在宿主机中创建的独立的虚拟空间。

仓库(Registry)
  • 公有仓库,Docker Hub,阿里,网易...

  • 私有仓库,企业内部搭建

    • Docker Registry,Docker 官方提供的镜像仓库存储服务
    • Harbor, 是 Docker Registry 的更高级封装,它除了提供友好的 Web UI 界面,角色和用户权限管理,用户操作审计等功能
  • 镜像访问地址形式 registry.devops.com/demo/hello:latest,若没有前面的 url 地址,则默认寻找 Docker Hub 中的镜像,若没有 tag 标签,则使用 latest 作为标签

  • 公有的仓库中,一般存在这么几类镜像

    • 操作系统基础镜像(CentOS,Ubuntu,suse,alpine)
    • 中间件(nginx,Redis,MySQL,Tomcat)
    • 语言编译环境(python,Java,golang)
    • 业务镜像(django-demo...)
      常用命令.jpg
  • 启动容器

  • 后台启动
    $ docker run --name nginx -d nginx:alpine

  • 查看 run 流程

  • 查看容器进程

  • 等同于在虚拟机中开辟了一块隔离的独立的虚拟空间

  • 启动容器的同时进入容器,-ti 与/bin/sh 或者/bin/bash 配套使用,意思未分配一个 tty 终端
    $ docker run --name nginx -ti nginx:alpine /bin/sh
    (注意:退出容器后,该容器会变成退出状态,因为容器内部的 1 号进程退出)

  • 实际上,在运行容器的时候,镜像地址后面跟的命令等于是覆盖了原有的容器的 CMD 命令,因此,执行的这些命令在容器内部就是 1 号进程,若该进程不存在了,那么容器就会处于退出的状态,比如,宿主机中执行

  1. echo 1,执行完后,该命令立马就结束了
  2. ping www.baidu.com,执行完后,命令的进程会持续运行
    $ docker run -d --name test_echo nginx:alpine echo 1,容器会立马退出
    $ docker run -d --name test_ping nginx:alpine ping www.baidu.com,容器不会退出,但是因为没有加-d 参数,因此一直在前台运行,若 ctrl+C 终止,则容器退出,因为 1 号进程被终止了
  • 映射端口,把容器的端口映射到宿主机中,-p <host_port>:<container_port>
    $ docker run --name nginx -d -p 8080:80 nginx:alpine
  • 资源限制,-cpuset-cpus 用于设置容器可以使用的 vCPU 核。-c,--cpu-shares 用于设置多个容器竞争 CPU 时,各个容器相对能分配到的 CPU 时间比例。假设有三个正在运行的容器,这三个容器中的任务都是 CPU 密集型的。第一个容器的 CPU 共享权值是 1024,其它两个容器的 CPU 共享权值是 512。第一个容器将得到 50% 的 CPU 时间,而其它两个容器就只能各得到 25% 的 CPU 时间了。如果再添加第四个 CPU 共享值为 1024 的容器,每个容器得到的 CPU 时间将重新计算。第一个容器的 CPU 时间变为 33%,其它容器分得的 CPU 时间分别为 16.5%、16.5%、33%。必须注意的是,这个比例只有在 CPU 密集型的任务执行时才有用。在四核的系统上,假设有四个单进程的容器,它们都能各自使用一个核的 100% CPU 时间,不管它们的 CPU 共享权值是多少。
    $ docker run --cpuset-cpus="0-3" --cpu-shares=512 --memory=500m nginx:alpine

run 容器流程图.jpg

容器数据持久化

  • 挂载主机目录
$ docker run --name nginx -d  -v /opt:/opt -v /var/log:/var/log nginx:alpine
$ docker run --name mysql -e MYSQL_ROOT_PASSWORD=123456 -d -v /opt/mysql/:/var/lib/mysql mysql:5.7
  • 使用 volumes 卷
$ docker volume ls
$ docker volume create my-vol
$ docker run --name nginx -d -v my-vol:/opt/my-vol nginx:alpine
$ docker exec -ti nginx touch /opt/my-vol/a.txt
  • 验证数据共享
$ docker run --name nginx2 -d -v my-vol:/opt/hh nginx:alpine
$ docker exec -ti nginx2 ls /opt/hh/
a.txt
  • 进入容器或者执行容器内的命令
$ docker exec -ti <container_id_or_name> /bin/sh
$ docker exec -ti <container_id_or_name> hostname
  • 主机与容器之间拷贝数据
    主机拷贝到容器
$ echo '123'>/tmp/test.txt
$ docker cp /tmp/test.txt nginx:/tmp
$ docker exec -ti nginx cat /tmp/test.txt
123

容器拷贝到主机
$ docker cp nginx:/tmp/test.txt ./

  • 查看容器日志

查看全部日志
$ docker logs nginx

实时查看最新日志
$ docker logs -f nginx

从最新的 100 条开始查看
$ docker logs --tail=100 -f nginx

  • 停止或者删除容器

停止运行中的容器

$ docker stop nginx

启动退出容器
$ docker start nginx

删除退出容器
$ docker rm nginx

删除运行中的容器
$ docker rm -f nginx

  • 查看容器或者镜像的明细

查看容器详细信息,包括容器 IP 地址等
$ docker inspect nginx

查看镜像的明细信息
$ docker inspect nginx:alpine

Django 应用容器化实践

django 项目介绍

Dockerfile

Dockerfile 是一堆指令,在 docker build 的时候,按照该指令进行操作,最终生成我们期望的镜像

  • FROM 指定基础镜像,必须为第一个命令
格式:
	FROM <image>
	FROM <image>:<tag>
示例:
	FROM mysql:5.7
注意:
	tag是可选的,如果不使用tag时,会使用latest版本的基础镜像
  • MAINTAINER 镜像维护者的信息
格式:
	MAINTAINER <name>
示例:
    MAINTAINER cuijianzhe
    MAINTAINER 598941324@qq.com
    MAINTAINER Jianzhe Cui <598941324@qq.com>
  • COPY|ADD 添加本地文件到镜像中
格式:
	COPY <src>... <dest>
示例:
    ADD hom* /mydir/          # 添加所有以"hom"开头的文件
    ADD test relativeDir/     # 添加 "test" 到 `WORKDIR`/relativeDir/
    ADD test /absoluteDir/    # 添加 "test" 到 /absoluteDir/
  • WORKDIR 工作目录
格式:
	WORKDIR /path/to/workdir
示例:
    WORKDIR /a  (这时工作目录为/a)
注意:
	通过WORKDIR设置工作目录后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT、ADD、COPY等命令都会在该目录下执行
  • RUN 构建镜像过程中执行命令
格式:
	RUN <command>
示例:
    RUN yum install nginx
    RUN pip install django
    RUN mkdir test && rm -rf /var/lib/unusedfiles
注意:
	RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,可以在构建时指定--no-cache参数,如:docker build --no-cache
  • CMD 构建容器后调用,也就是在容器启动时才进行调用
格式:
    CMD ["executable","param1","param2"] (执行可执行文件,优先)
    CMD ["param1","param2"] (设置了ENTRYPOINT,则直接调用ENTRYPOINT添加参数)
    CMD command param1 param2 (执行shell内部命令)
示例:
    CMD ["/usr/bin/wc","--help"]
    CMD ping www.baidu.com
注意:
	CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。
  • ENTRYPOINT 设置容器初始化命令,使其可执行化
格式:
    ENTRYPOINT ["executable", "param1", "param2"] (可执行文件, 优先)
    ENTRYPOINT command param1 param2 (shell内部命令)
示例:
    ENTRYPOINT ["/usr/bin/wc","--help"]
注意:
	ENTRYPOINT与CMD非常类似,不同的是通过docker run执行的命令不会覆盖ENTRYPOINT,而docker run命令中指定的任何参数,都会被当做参数再次传递给ENTRYPOINT。Dockerfile中只允许有一个ENTRYPOINT命令,多指定时会覆盖前面的设置,而只执行最后的ENTRYPOINT指令
  • ENV
格式:
    ENV <key> <value>
    ENV <key>=<value>
示例:
    ENV myName John
    ENV myCat=fluffy
  • EXPOSE
格式:
    EXPOSE <port> [<port>...]
示例:
    EXPOSE 80 443
    EXPOSE 8080
    EXPOSE 11211/tcp 11211/udp
注意:
    EXPOSE并不会让容器的端口访问到主机。要使其可访问,需要在docker run运行容器时通过-p来发布这些端口,或通过-P参数来发布EXPOSE导出的所有端口

Dockerfile 解释.png

  • Dockerfile
    git clone https://gitee.com/agagin/python-demo.git
    当前工作路径:
    image.png
[root@k8s-master python-demo]# cat Dockerfile 
# This my first django Dockerfile
# Version 1.0

# Base images 基础镜像
FROM centos:centos7.5.1804

#MAINTAINER 维护者信息
LABEL maintainer="598941324@qq.com"

#ENV 设置环境变量
    ENV LANG en_US.UTF-8
    ENV LC_ALL en_US.UTF-8

#RUN 执行以下命令
RUN curl -so /etc/yum.repos.d/Centos-7.repo http://mirrors.aliyun.com/repo/Centos-7.repo
RUN yum install -y  python36 python3-devel gcc pcre-devel zlib-devel make net-tools

#工作目录
WORKDIR /opt/myblog

#拷贝文件至工作目录
COPY . .

#安装nginx
RUN tar -zxf nginx-1.13.7.tar.gz -C /opt  && cd /opt/nginx-1.13.7 && ./configure --prefix=/usr/local/nginx \
&& make && make install && ln -s /usr/local/nginx/sbin/nginx /usr/bin/nginx

RUN cp myblog.conf /usr/local/nginx/conf/myblog.conf

#安装依赖的插件
RUN pip3 install -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com -r requirements.txt

RUN chmod +x run.sh && rm -rf ~/.cache/pip

#EXPOSE 映射端口
EXPOSE 8002

#容器启动时执行命令
CMD ["./run.sh"]

定制化基础镜像

[root@k8s-master python-demo]# cat Dockerfile-base 
[root@k8s-master python-demo]# cat Dockerfile-base 
# Base images 基础镜像
FROM centos:centos7.5.1804

#MAINTAINER 维护者信息
LABEL maintainer="598941324@qq.com"

#ENV 设置环境变量
ENV LANG en_US.UTF-8
ENV LC_ALL en_US.UTF-8

#RUN 执行以下命令
RUN curl -so /etc/yum.repos.d/Centos-7.repo http://mirrors.aliyun.com/repo/Centos-7.repo
RUN yum install -y  python36 python3-devel gcc pcre-devel zlib-devel make net-tools

COPY nginx-1.13.7.tar.gz  /opt

#安装nginx
RUN tar -zxf /opt/nginx-1.13.7.tar.gz -C /opt  && cd /opt/nginx-1.13.7 && ./configure --prefix=/usr/local/nginx && make && make install && ln -s /usr/local/nginx/sbin/nginx /usr/bin/nginx

构建基础镜像

[root@k8s-master python-demo]# docker build . -t centos-python3-nginx:v1 -f Dockerfile-base
[root@k8s-master python-demo]# docker tag centos-python3-nginx:v1 10.200.51.36:5000/base/centos-python3-nginx:v1
[root@k8s-master python-demo]# docker push 10.200.51.36:5000/base/centos-python3-nginx:v1

简化 Dockerfile

[root@k8s-master python-demo]# cat Dockerfile-optimized 
# This my first django Dockerfile
# Version 1.0

# Base images 基础镜像
FROM centos-python3-nginx:v1

#MAINTAINER 维护者信息
LABEL maintainer="598941324@qq.com"

#工作目录
WORKDIR /opt/myblog

#拷贝文件至工作目录
COPY . .

RUN cp myblog.conf /usr/local/nginx/conf/myblog.conf

#安装依赖的插件
RUN pip3 install -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com -r requirements.txt

RUN chmod +x run.sh && rm -rf ~/.cache/pip

#EXPOSE 映射端口
EXPOSE 8002

#容器启动时执行命令
CMD ["./run.sh"]

构建镜像
docker build . -t myblog -f Dockerfile-optimized

运行 MySQL

docker run -d -p 3306:3306 --name mysql -v /opt/mysql/mysql-data/:/var/lib/mysql -e MYSQL_DATABASE=myblog -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7

查看数据库

$ docker exec -ti mysql bash
#/ mysql -uroot -p123456
#/ show databases;

启动 Django 应用

启动容器

docker run -d -p 8002:8002 --name myblog -e MYSQL_HOST=10.200.51.36 -e MYSQL_USER=root -e MYSQL_PASSWD=123456 myblog

查看应用运行状态

[root@k8s-master python-demo]# docker exec -it myblog bash
[root@3087587eb981 myblog]# ps -aux 
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          1  0.1  0.0  13284  1436 ?        Ss   10:49   0:00 /bin/bash ./run.sh
root         10  0.0  0.0  20544  1564 ?        S    10:50   0:00 nginx: master process nginx -c /usr/local/nginx/conf/myblog.conf -g daemon off;
root         11  0.6  0.0 145272 30004 ?        S    10:50   0:00 uwsgi --ini ./uwsgi.ini
nobody       12  0.0  0.0  20984  1068 ?        S    10:50   0:00 nginx: worker process
root         14  0.0  0.0 219004 25500 ?        Sl   10:50   0:00 uwsgi --ini ./uwsgi.ini
root         15  0.0  0.0 219004 25504 ?        Sl   10:50   0:00 uwsgi --ini ./uwsgi.ini
root         18  0.6  0.0  13404  2016 pts/0    Ss   10:50   0:00 bash
root         32  0.0  0.0  53312  1864 pts/0    R+   10:50   0:00 ps -aux

migrate 进行数据库同步

$ docker exec -ti myblog bash
#/ python3 manage.py makemigrations
#/ python3 manage.py migrate
#/ python3 manage.py createsuperuser

创建超级用户
docker exec -ti myblog python3 manage.py createsuperuser

收集静态文件
docker exec -ti myblog python3 manage.py collectstatic

访问 10.200.51.36:8002/admin

  • 构建镜像,替换默认编码:
[root@k8s-master ~]# mkdir mysql
[root@k8s-master ~]# cd mysql/
[root@k8s-master mysql]# vim Dockerfile
[root@k8s-master mysql]# vim my.cnf
[root@k8s-master mysql]# cat my.cnf 
[mysqld]
user=root
character-set-server=utf8
lower_case_table_names=1

[client]
default-character-set=utf8
[mysql]
default-character-set=utf8

!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/
[root@k8s-master mysql]# cat Dockerfile 
FROM mysql:5.7
COPY my.cnf /etc/mysql/my.cnf

## CMD或者ENTRYPOINT默认继承
[root@k8s-master python-demo]# 
[root@k8s-master python-demo]# docker build . -t mysql:5.7-utf8
Sending build context to Docker daemon  2.104MB
Step 1/2 : FROM mysql:5.7
 ---> 413be204e9c3
Step 2/2 : COPY my.cnf /etc/mysql/my.cnf
 ---> 0e412c9aaf3c
Successfully built 0e412c9aaf3c
Successfully tagged mysql:5.7-utf8
[root@k8s-master python-demo]# docker tag mysql:5.7-utf8 10.200.51.36:5000/mysql:5.7-utf8
[root@k8s-master python-demo]# docker push 10.200.51.36:5000/mysql:5.7-utf8

删除旧的 MySQL 容器,使用新镜像启动,不用再次初始化

[root@k8s-master python-demo]# docker rm -f mysql 
mysql   
[root@k8s-master python-demo]# rm -rf /opt/mysql/mysql-data/*
[root@k8s-master python-demo]# docker run -d -p 3306:3306 --name mysql -v /opt/mysql/mysql-data/:/var/lib/mysql -e MYSQL_DATABASE=myblog -e MYSQL_ROOT_PASSWORD=123456 10.200.51.36:5000/mysql:5.7-utf8
9b3af65a50c3a88858567bd190b6388c98016a79687ee92370a85b683b3c77ea

查看 MySQL 字符集

[root@k8s-master mysql]# docker exec -it mysql bash
root@d7440060e2a6:/# mysql -uroot -p123456
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.29 MySQL Community Server (GPL)

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show variables like '%charac%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8                       |
| character_set_connection | utf8                       |
| character_set_database   | utf8                       |
| character_set_filesystem | binary                     |
| character_set_results    | utf8                       |
| character_set_server     | utf8                       |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.01 sec)

重新 migrate

$ docker exec -ti myblog bash
#/ python3 manage.py makemigrations
#/ python3 manage.py migrate
#/ python3 manage.py createsuperuser

Docker 网络详见:https://www.cjzshilong.cn/articles/2019/03/27/1553657246955.html


标题:Django应用容器化
作者:cuijianzhe
地址:https://cuijianzhe.github.io/articles/2020/04/12/1586677258146.html