docker前后端分离部署(flask+vue)和编排

[一、docker安装MySql和Redis并启动]
- [1. docker安装]
- [2.docker启动安装的镜像]
- [3. 查看docker启动镜像的时候所用的命令]
- [4. 停止和删除镜像容器]
- [5. 登陆和修改、提交镜像]
[二、每个镜像都有资源彼此独立]
- [1. 如何查看docker里面container的ip]
- [2. docker创建的容器具有ip的原因和通信方式]
- [3. docker-compose编排容器并启动]
- [4. 需要注意mysql和redis的ip修改]
[三、分离部署docker+nginx+uwsgi+mysql+redis]
- [1. 设计图和项目路径]
- [2. Dockerfile编写]
[四、uwsgi和docker爬坑]
- [1. 报错invalid request block size: zxx...skip]
- [2. 启动出现!!! no internal routing support, rebuild with pcre support !!!]
- [3. uwsgi提示 No such file or directory [core/utils.c line 3654]]
- [4. 提示failed to build: COPY failed: stat /var/lib/docker/tmp:no such file or directory]
- [5. mysql提示Failed to get stat for directory pointed out by --secure-file-priv]
- [6. Supplied value : /var/lib/mysql-files]
[五、项目展示和项目地址]
[1. docker-compose编排成功后的截图]
[2. 项目界面的截图]
[3.写在最后]

今天给大家带来前后端分离项目下的docker的部署和启动,到最终的打包提交到dockerhub,以及爬坑记录。旨在解决同道小伙伴们的痛点。
​刚学习docker,不足之处望请谅解,虚心接受大神指点,转注出,诚谢~ 文末附项目效果展示和源码地址。

一、docker安装MySql和Redis并启动

官网命令传送门==> docker命令

1. docker安装

  • 查询有哪些镜像
  • $ docker search mysql
    
  • 安装指定的镜像(在此之前请先配制好镜像加速)
  • $ docker pull mysql:8.0.18
    
  • 安装默认最新镜像
  • $ docker pull mysql
    # 或docker pull mysql:latest
    

    同理安装Redis

    2. docker启动安装的镜像

  • 查询本地安装了的镜像
  • $ docker images
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    mysql               latest              9b51d9275906        8 days ago          547MB
    redis               latest              7eed8df88d3b        2 weeks ago         98.2MB
    
  • 启动Mysql
  • # 将docker的mysql镜像以守护进程的方式创建实例mysql-demo(容器)
    # 该实例的端口为3306对应的宿主机上的12345,初始化的数据库密码为5201020116.
    # 也可以将宿主机的数据库的配置挂载到mysql-demo对应的位置
    $ docker run -p 12345:3306 --name mysql-demo -e MYSQL_ROOT_PASSWORD=5201020116 -d mysql
    

    因为我的mysql的宿主机环境已经安装了,所以宿主机端口不能在用3306,改为了12345。

  • 启动Redis
  • # 默认redis容器里是没有配置文件的(可在容器的/etc/查看redis.conf不存在),因而需要在创建容器时映射进来
    # 设置密码直接使用--requirepass "你的密码"即可
    # -i表示以交互模式运行容器,-t表示重新分配伪终端, -d以守护进程方式运行; -v 表示映射文件;-p端口映射
    $ docker run -itd --name redis-demo -v /etc/redis/redis.conf:/etc/redis.conf -p 9909:6379
     --restart=always redis:latest redis-server --appendonly yes --requirepass "5201020116"
    # 查看刚创建的容器的信息(截取部分)
    $ docker ps -l
    CONTAINER ID      IMAGE      CREATED     STATUS             PORTS                    NAMES
    a83ef0e487e7   redis:latest  4 minutes ago   Up 4 minutes   0.0.0.0:9909->6379/tcp   redis-demo
    # 再次进入这个容器
    $ docker exec -it a83ef0e487e7 /bin/bash
    # 验证是否成功
    root@a83ef0e487e7:/data# redis-cli
    127.0.0.1:6379> auth 5201020116
    127.0.0.1:6379>
    

    安装启动nginx同理。

    3. 查看docker启动镜像的时候所用的命令

    $ docker ps -a --no-trunc
    

    4. 停止和删除镜像容器

    # 查看所有的容器
    $ docker ps -a
    # 停止/重启/删除容器 (已运行需要先停止再删除)
    $ docker container stop/restart/rm  a83ef0e487e7#容器ID
    # 直接强制删除
    $ docker rm -f a83e#容器ID
    # #删除镜像image,删除前需要保证没有container引用这个镜像
    $ docker rmi 9b51d9275906   #镜像id
    # 删除所有镜像
    $ docker rmi $(docker images -q)
    # 删除所有没有标签的镜像
    $ docker rmi $(docker images -q | awk '/^<none>/ { print $3 }')
    

    5. 登陆和修改、提交镜像

    # 登录dockerhub
    $ docker login -u jackmin1314   # 你的dockerhub账户名
    # 提交前切记修改镜像为 账户名/镜像名:tag
    $ docker tag fe2880e71109 jackmin1314/spider_flask:latest
    # 提交镜像到本地
    $ docker commit -a "jackmin1314 <1416@qq.com>" -m "this is test" 5bca95es95 myubuntu:v1
    # 提交到远程dockerhub上面
    $ docker push jackmin1314/spider_flask:latest
    The push refers to repository [docker.io/jackmin1314/spider_redis]
    a64d7a130512: Pushed
    0554f8c96c61: Pushed
    493605b7d1c9: Pushed
    c742d444d284: Pushed
    5216338b40a7: Mounted from library/alpine
    latest: digest: sha256:0554f8c96c61....ea3c01 size: 1777
    

    二、每个镜像都有资源,彼此独立

    1. 如何查看docker里面container的ip

    $ docker inspect --format '{{ .NetworkSettings.IPAddress }}' 053e4f11df7a
    

    因而想要让docker内部容器间访问就需要通过ip来实现。例如后端python项目和mysql交互。

    2. docker创建的容器具有ip的原因

  • ​宿主机在安装docker后,docker会在宿主机上生成一张docker虚拟网卡,docker网卡通过NAT的方式为每一个容器分配ip,容器同处于docker网段下,因而容器间通信,可以通过ip。
  • 而容器和宿主机器通信,则是通过docker虚拟网卡进行转发路由。
  • 镜像创建了容器后,容器名会对应容器ip(在该容器的host有映射),因而可以通过容器名执行相关操作.
  • nginx的dockerfile

    FROM nginx:latest
    LABEL  auth=jackmin1314   maintainer="1416825008@qq.com"
    RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
        echo "Asia/Shanghai" > /etc/timezone
    # 移除nginx容器的default.conf文件、nginx配置文件
    RUN rm  /etc/nginx/conf.d/default.conf
    RUN rm  /etc/nginx/nginx.conf
    # 把主机的nginx.conf文件复制到nginx容器的/etc/nginx文件夹下
    ADD ./docker/web/nginx.conf /etc/nginx/
    # 容器间暴露8080端口.如果是云服务器部署,记得在安全组添加开放端口8080。
    # 也可以在docker run -p指定具体的,或者-P默认expose暴露的端口
    EXPOSE 8080
    # CMD命令用于容器启动时执行,而不像RUN的镜像构建时候运行
    # 使用daemon off的方式将nginx运行在前台保证镜像不退出
    CMD ["nginx", "-g", "daemon off;"]
    

    redis的dockerfile

    FROM    redis:latest
    WORKDIR /app/redis/
    LABEL   auth=jackmin1314    maintainer="1416825008@qq.com"
    RUN rm -rf /etc/redis/redis.conf
    RUN mkdir -p   /var/log/redis/
    RUN touch   /var/log/redis/redis-server.log
    RUN chmod -R 777 /var/log/redis/
    RUN chmod 777 /var/log/redis/redis-server.log
    COPY ./docker/redis/redis.conf .
    EXPOSE  6379
    #CMD ["/usr/local/bin/redis-server", "/app/redis/redis.conf"]
    

    mysql的dockerfile

    FROM mysql:latest
    LABEL     auth=jackmin1314    maintainer="1416825008@qq.com"
    RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
        echo "Asia/Shanghai" > /etc/timezone
    #WORKDIR /app
    # 拷贝mysql_spider的初始化数据库和表的脚本
    #COPY ./Mysql_Init_Script.sql /app
    COPY ./docker/mysql/Mysql_Init_Script.sql /docker-entrypoint-initdb.d/
    RUN chmod -R 775 /docker-entrypoint-initdb.d
    RUN touch /var/lib/mysql-files
    RUN chmod -R 777 /var/lib/mysql-files
    

    uwsgi的dockerfile

    FROM alpine:latest
    LABEL auth=jackmin1314  maintainer="1416825008@qq.com"
    RUN mkdir -p /app/BackServer/
    WORKDIR /app/BackServer
    COPY ./BackServer/ .
    RUN chmod  -R 777 /app/BackServer/
    RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g'  /etc/apk/repositories && \
        apk update && \
        apk add python3 py3-pip python3-dev git gcc g++ linux-headers libstdc++ libffi-dev&& \
        apk add uwsgi-python3 tzdata libxml2-dev libxslt-dev openssl-dev && \
        cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
        echo "Asia/Shanghai" > /etc/timezone && \
        pip3 install --index-url=http://mirrors.aliyun.com/pypi/simple/  --trusted-host mirrors.aliyun.com -r requirements.txt && \
        apk del py3-pip python3-dev git tzdata gcc g++ linux-headers && \
        cd / && \
        rm -rf   ~/.cache/pip /var/cache/apk/*
    EXPOSE 9999
    CMD ["uwsgi", "--ini", "uwsgi.ini"]
    

    3. docker-compose编排容器并启动

    docker-compose.yml编写启动的顺序(依赖关系)要注意 参考redis -> mysql -> uwsgi -> nginx。例外,一旦指定了compose的某个service的上下文(主路径),那么dockerfile的路径将以compose设定为准,而不是dockerfile所在目录。

    version: "3.7"
    services:
        redis:
            hostname:   spider-redis
            # 根据BackServer/Config/config.py配置
            container_name: spider-redis    # 不指定则会系统自动分配名称
            restart: always  # always表容器运行发生错误时一直重启
            build:
                context:    ./
                dockerfile: ./docker/redis/Dockerfile 
            #command: /usr/local/bin/redis-server /usr/local/etc/redis.conf
            environment:    # environment 一定要在command下面
                - TZ=Asia/Shanghai
            volumes:
                - /etc/localtime:/etc/localtime:ro  # 设置容器时区与宿主机保持一致
                #- ./docker/redis/redis.conf:/usr/local/etc/redis.conf
            privileged: true
            ports:
                - "6379:6379"
            tty: true
        mysql:
            hostname:   spider-mysql
            container_name: spider-mysql
            restart:    always
            build:
                context: ./
                dockerfile: ./docker/mysql/Dockerfile
            #command:
            environment:
                # 这个根据项目BackServer的Config/config.py里面的设置对应
                - MYSQL_ROOT_PASSWORD=5201020116    # 配置数据库的密码
            volumes:
               # 初始化数据库信息- ./docker/mysql/Mysql_Init_Script.sql:/docker-entrypoint-initdb.d/  
                - ./docker/mysql/my.cnf:/etc/mysql/my.cnf    # 挂载配置文件-
                - /etc/localtime:/etc/localtime:ro  # 设置容器时区与宿主机保持一致
            ports:
                - "3306:3306"
        flask:
            hostname:   spider-flask
            container_name: spider-flask
            restart:    always
            build:  .   # 执行当前的目录下的dockerfile
                # context:    ./
                # dockerfile: ./docker/uwsgi_flask/Dockerfile
            volumes:
                - /etc/localtime:/etc/localtime:ro  # 设置容器时区与宿主机保持一致
            ports:
                - "9999:9999"
            links:
                - mysql
                - redis
            depends_on:
                - mysql
                - redis
        nginx:
            hostname:   spider-nginx
            container_name: spider-nginx
            restart:    always
            build:
                context:    ./
                dockerfile: ./docker/web/Dockerfile
            ports:
                - "8080:8080"   # 根据nginx.conf配置
                - "443:443"
            volumes:
                - ./dist/:/usr/share/nginx/html/dist
            links:
                - flask
            depends_on:
                - flask
    

    4. 需要注意mysql和redis的ip修改

    mysql和redis的ip不能是以前的localhost或者127.0.0.1.要改为容器名字作为ip,或者是容器的ip地址

    四、uwsgi和docker爬坑

    1. 报错invalid request block size: xxx...skip

    这个是比较常见的,问题出在请求的时候协议和对应uwsgi配置或启动不一致,例如docker里面通过nginx容器访问uwsgi需要通过.socket文件来,uwsgi配置的是http协议;或者本地开发过程中uwsgi启动或者配置时采用socket=127.0.0.1:9999,而浏览器是http请求,也会报错,具体看实际情况。

    2. 启动出现!!! no internal routing support, rebuild with pcre support !!!

    这个是没有内部路由支持,需要通过使用pcre重新构建。需要先停掉uwsgi项目,然后重构下载依赖,具体做法为

    # 卸载原有的uwsgi
    pip uninstall uwsgi
    # 安装pcre
    sudo apt-get install libpcre3 libpcre3-dev
    # 重新下载uwsgi --no-cache-dir意思是不从缓存中用上次编译的uwsgi文件
    pip install uwsgi --no-cache-dir
    

    3. uwsgi提示 No such file or directory [core/utils.c line 3654]

    我的路径没有问题,而且,可为何还是提示没有这个文件呢?检查文件内容是否有注释,。

    注意一下几点,但不一定全是:

  • 注意启动的时候 --ini uwsgi_flask.ini 后面没有空格
  • 检查文件.ini内容是否有注释,将注释全部删除即可
  • 检查文件.ini内容是否有空格,将空格全部删除
  • 路径有误!将当前含有uwsgi_flask.ini的目录挂载到容器里(我的uwsgi.ini在BackServer里面)
  • # When I fixed it, all started work as expected.
    docker run -itd --name flask_env_container2 -v $PWD/BackServer:/app -p 9999:9999 flask_env:latest uwsgi --plugin=python3  --ini uwsgi.ini
    

    4. 提示failed to build: COPY failed: stat /var/lib/docker/tmp:no such file or directory

    本质上还是路径不对,检查文件别写错了。例外注意/dirname/dirname/区别

  • dockerfile没有指定上下文(就是你运行的dockerfile所在目录就是主路径,后面复制文件等操作以此相对应)

  • docker-compose文件已经指定了上下文,后面你又执行了某个路径下的dockerfile,那么对于当前service而言,你的dockerfile的上下文不再是dockerfile所在目录,而是你compose所指定的路径(context:)

  • 就是copy 或者add 后面的路径没有/ 例如 copy a /mydir 应该改成 copy a /mydir/

  • 5. mysql提示Failed to get stat for directory pointed out by --secure-file-priv

    vim /etc/my.cnf     # (数据库配置文件)
    secure-file-priv="/"    # (即可将数据导出到任意目录)
    

    如果是通过配置文件添加的,则修改my.cnf

    # 添加[mysqld]
    secure_file_priv=""
    

    6. Supplied value : /var/lib/mysql-files

    /var/lib/mysql-files 文件是否存在或者权限问题

    touch /var/lib/mysql-files
    chown -R 777 /var/lib/mysql-files
    

    五、项目展示和项目地址

    1. docker-compose编排成功后的截图

    flask成功创建界面:

    2. 项目界面

    基于python flask和前端Vue.js、Element-ui等前后端分离的后台用户管理,整合爬虫项目。提供了CSRF防护,权限验证,数据库备份导出excel,日志记录,定时任务,邮箱发送等功能,详见Github
    一两个月的努力,希望大家能够支持,谢谢。期待您的start~

    登陆界面: