Docker篇章12:用docker-compose部署構建django+uwsgi+redis+mysql項目


  • 上圖是上一篇章,我們手動構建四個容器,分別對應Nginx,Django Uwsgi,Redis,MySQL器,部署一個web項目。然而在實際生產環境中,我們定義數量較多的docker容器,並且伴隨容器之間關系比較復雜。一個個去構建容器,不僅效率低下,而且容器出錯。而docker-compose可以定義容器集群的編排

1.docker-compose什么鬼

  • 它用來定義和運行復雜應用Docker工具。使用docker-compose后不再需要使用shell腳本來逐一創建和啟動容器,還可以通過docker-compose.yml 文件構建和管理復雜容器組合

  • 下載docker-compose

    # 下載並安裝docker-compose
    curl -L https://github.com/docker/compose/releases/download/1.14.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose            
    # 設置權限
    chmod +x /usr/local/bin/docker-compose
    # 檢查
    docker-compose -version   
    

2.docker-compose組合容器

  • 通過docker-compose編排並啟動4個容器,這更接近於實際生成環境下的部署。

    1.Django + Uwsgi容器:應用程序,后端

    2.MySQL容器:數據庫服務

    3.Redis容器:緩存服務

    4.Nginx容器:反向代理,處理靜態資源

這四個容器的依賴關系是:Django+Uwsgi 容器依賴 Redis 容器和 MySQL 容器,Nginx 容器依賴Django+Uwsgi容器。這四個容器別名及通信端口如下圖所示:

3.Docker-compose部署Django項目布局樹形圖

  • 在根目錄新建一個文件夾build_project,用於項目構建,根目錄下創建項目目錄,這樣不同django項目可以共享compose文件。結構目錄如下

    /build_project/
    ├── compose# 存放各容器服務Dockerfile配置文件
    │   ├── mysql
    │   │   ├── conf
    │   │   │   └── my.cnf# mysql配置文件
    │   │   ├── init
    │   │   │   └── init.sql# mysql初始化啟動腳本
    │   │   └── sqldata# sql數據
    │   │       └── west_coast.sql
    │   ├── nginx
    │   │   ├── Dockerfile# 構建nginx鏡像的dockerfile
    │   │   ├── log# 掛載保存nginx容器內日志
    │   │   ├── nginx.conf# nginx配置文件
    │   │   ├── phone.tar.gz# vue靜態打包文件手機端
    │   │   └── web.tar.gz# vue靜態打包文件pc端
    │   ├── redis
    │   │   └── redis.conf# redis配置文件
    │   └── uwsgi# 掛載保存django+uwsgi容器內uwsgi日志
    ├── docker-compose.yml# 部署編排文件
    └── west_coast__company_project# 項目目錄
        ├── app# 存在項目app
        ├── Dockerfile# # 構建Django+Uwsgi鏡像的dockerfile
        ├── logs# 項目日志
        ├── manage.py
        ├── pip.conf# pypi源設置。加速pip install
        ├── requirements.txt# django項目依賴
        ├── run.sh# 啟動Django+Uwsgi 腳本
        ├── static# 靜態文件
        ├── uwsgi.ini# uwsgi配置
        ├── uwsgi.log
        └── west_coast__company_project# Django項目配置文件
            ├── __init__.py
            ├── settings.py
            ├── urls.py
            └── wsgi.py
    
    

4.基礎鏡像下載

nginx: docker pull nginx
redis: docker pull redis:3.2
mysql: docker pull mysql:5.6
python3: docker pull python:3.6

5.編寫Dockerfile

  • 通過docker-compose.yml,編排了4項容器服務,別名分別為redis, db, nginx和web:

    version: "3"
    
    volumes: # 自定義數據卷,位於宿主機/var/lib/docker/volumes內
      myproject_db_vol: # 定義數據卷同步容器內mysql數據
      myproject_redis_vol: # 定義數據卷同步redis容器內數據
    
    services:
      redis:
        image: redis:3.2
        volumes:
           - myproject_redis_vol:/data #給redis數據備份
           - ./compose/redis/redis.conf:/etc/redis/redis.conf # 掛載redis配置文件
        expose:
           - "6379"
        restart: always # always表容器運行發生錯誤時一直重啟
      db:
        image: mysql:5.7
        environment:
           - MYSQL_ROOT_PASSWORD=123456 # 數據庫密碼
           - MYSQL_DATABASE=west_coast # 數據庫名稱
           - MYSQL_USER=xujunkai # 數據庫用戶名
           - MYSQL_PASSWORD=123456 # 用戶密碼
    
        volumes:
           - myproject_db_vol:/var/lib/mysql:rw # 掛載數據庫數據, 可讀可寫
           - ./compose/mysql/sqldata:/opt:rw
           - ./compose/mysql/conf/my.cnf:/etc/mysql/my.cnf # 掛載配置文件
           - ./compose/mysql/init:/docker-entrypoint-initdb.d/ # 掛載數據初始化sql腳本
        ports:
           - "3306:3306" # 與配置文件保持一致,映射端口
        restart: always
    
      web:
        build: ./west_coast__company_project # 使用west_coast__company_project目錄下的Dockerfile
        ports:
           - "9000:9000"
        expose:
           - "9000"
        volumes:
           - ./west_coast__company_project:/var/api/west_coast__company_project # 掛載項目代碼
           - ./compose/uwsgi:/tmp # 掛載uwsgi日志
        links:
           - db
           - redis
        depends_on: # 依賴關系
           - db
           - redis
        environment:
           - DEBUG=False
        restart: always
        tty: true
        stdin_open: true
    
      nginx:
        build: ./compose/nginx
        ports:
           - "80:80"
           - "8000:8000"
        expose:
           - "80"
           - "8000"
        volumes:
           - ./compose/nginx/log:/var/log/nginx # 掛載日志
        links:
           - web
        depends_on:
           - web
        restart: always
    

6.編寫web鏡像

  • 構建west_coast__company_project/Dockerfile

    # 建立 python3.6 環境
    FROM python:3.6
    MAINTAINER xujunkai<xujunkaipy@163.com>
     # 設置 python 環境變量
    ENV PYTHONUNBUFFERED 1
    COPY pip.conf /root/.pip/pip.conf
    # 容器內創建項目目錄
    RUN mkdir -p /opt/west_coast__company_project
    WORKDIR /opt/west_coast__company_project
    # 將當前目錄下文件 放入容器指定目錄
    ADD . /opt/west_coast__company_project
    # 更新pip
    RUN /usr/local/bin/python -m pip install --upgrade pip
    
    # 安裝依賴
    RUN pip3 install -r requirements.txt
    
    # 啟動項目腳本 增加執行權限
    RUN chmod +x ./run.sh
    
    
    
  • run.sh

    #!/bin/bash
    # 生成數據庫可執行文件,
    # 根據數據庫可執行文件來修改數據庫
    # 用 uwsgi啟動 django 服務
    python3 manage.py makemigrations && python3 manage.py migrate && uwsgi --ini /opt/west_coast__company_project/uwsgi.ini
    
    
  • uwsgi.ini配置

    [uwsgi]
    project=west_coast__company_project
    
    base=/opt
    # the base directory (full path)
    # 指定項目的絕對路徑的第一層路徑(很重要)
    chdir = %(base)/%(project)
    
    # Django's wsgi file
    # 指定項目的 wsgi.py文件
    # 寫入相對路徑即可,這個參數是以chdir參數為相對路徑
    module = %(project).wsgi:application
    master = true
    processes = 2
    socket = 0.0.0.0:9000
    vacuum = true
    max-requests = 5000
    pidfile=/tmp/%(project)-master.pid
    daemonize=/tmp/%(project)-uwsgi.log
    #設置一個請求的超時時間(秒),如果一個請求超過了這個時間,則請求被丟棄
    harakiri = 60
    post buffering = 8192
    buffer-size= 65535
    #當一個請求被harakiri殺掉會,會輸出一條日志
    harakiri-verbose = true
    #開啟內存使用情況報告
    memory-report = true
    #設置平滑的重啟(直到處理完接收到的請求)的長等待時間(秒)
    reload-mercy = 10
    #設置工作進程使用虛擬內存超過N MB就回收重啟
    reload-on-as= 1024
    python-autoreload=1
    
    

7.編寫Nginx鏡像

  • Nginx鏡像使用Dockerfile如下所述:

    FROM nginx:latest
    # 刪除原有配置文件
    RUN rm /etc/nginx/conf.d/default.conf
    # 靜態文件拷貝容器,並解壓
    ADD phone.tar.gz /opt/
    ADD web.tar.gz /opt/
    # 添加新配置文件
    ADD ./nginx.conf /etc/nginx/conf.d/
    # 關閉守護模式
    CMD ["nginx","-g","daemon off;"]
    
    
  • nginx.conf

    server {
            listen       80 default_server;
            listen       [::]:80 default_server;
            server_name  localhost;
            location / {
                    root /opt/web/dist;
    {
    root /opt/phone/dist;
    }
                    index index.html;
                    try_files $uri $uri/ /index.html;
            }
            location ~.*(jpg|jpeg|png|gif|ico|css|js)$ {
                    root /opt/web/dist;
    {
    root /opt/phone/dist;
    }
                    expires 365d;
            }
            error_page 404 /404.html;
                location = /40x.html {
            }
    
            error_page 500 502 503 504 /50x.html;
                location = /50x.html {
            }
        }
        server {
            listen 8000;
            server_name web;
            location / {
                # 指定Docker-compose web服務的端口。反向代理
                uwsgi_pass web:9000;
                uwsgi_read_timeout 600;
                uwsgi_connect_timeout 600;
                uwsgi_send_timeout 600;
                include    uwsgi_params;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $http_host;
                proxy_redirect off;
                proxy_set_header X-Real-IP  $remote_addr;
                    }
        }
    
        access_log /var/log/nginx/access.log main;
        error_log /var/log/nginx/error.log warn;
    
        server_tokens off;
    

8.編寫MySQL容器

  • 之前我們已經從官網拉取鏡像,用官網鏡像即可,只需更改MySQL相關配置,

    # compose/mysql/conf/my.cnf
    [mysqld]
    user=mysql
    default-storage-engine=INNODB
    character-set-server=utf8
    
    port            = 3306 # 這里端口於docker-compose里映射端口保持一致
    #bind-address= localhost
    
    basedir         = /usr
    datadir         = /var/lib/mysql
    tmpdir          = /tmp
    pid-file        = /var/run/mysqld/mysqld.pid
    socket          = /var/run/mysqld/mysqld.sock
    skip-name-resolve# 這個參數是禁止域名解析的,遠程訪問推薦開啟skip_name_resolve。
    
    [client]
    port = 3306
    default-character-set=utf8
    
    [mysql]
    no-auto-rehash
    default-character-set=utf8
    
    
  • 當然我們需要設置啟動腳本命令。這里給docker-compose.yml里設置的MySQL的環境變量要一致。

    GRANT ALL PRIVILEGES ON west_coast.* TO xujunkai@"%" IDENTIFIED BY "123456";
    FLUSH PRIVILEGES;
    

9.編寫redis容器配置

  • 這里使用默認配置

    # compose/redis/redis.conf
    注釋掉 bind 127.0.0.1 即可
    

10.修改django項目settings.py

  • 在這里修改mysql,redis服務連接配置

    # 生產環境設置 Debug = False
    Debug = False
    ALLOWED_HOSTS = ["*"] #或是你的服務的IP
    
    # 設置數據庫。這里用戶名和密碼必需和docker-compose.yml里mysql環境變量保持一致
     DATABASES = {
         'default': {
             'ENGINE': 'django.db.backends.mysql',
             'NAME': 'myproject', # 數據庫名
             'USER':'xujunkai', # 你設置的用戶名 - 非root用戶
             'PASSWORD':'123456', # # 換成你自己密碼
             'HOST': 'db', # 注意:這里使用的是db別名,docker會自動解析成ip
             'PORT':'3306', # 端口
        }
     }
     
     # 設置redis緩存。這里密碼為redis.conf里設置的密碼
     CACHES = {
         "default": {
             "BACKEND": "django_redis.cache.RedisCache",
             "LOCATION": "redis://redis:6379/1", #這里直接使用redis別名作為host ip地址
             "OPTIONS": {
                 "CLIENT_CLASS": "django_redis.client.DefaultClient",
                 # "PASSWORD": "yourpassword", # 換成你自己密碼
             },
         }
     }
    

11.使用docker-compose構建鏡像並啟動容器組

# 在docker-compose.yml所在文件夾下。輸入指令
sudo docker-compose build
# 查看已生成的鏡像
sudo docker images
# 啟動容器組服務
sudo docker-compose up
# 查看運行中的容器
sudo docker ps

# 重新構建
docker-compose up --build -d
  • 可以看到運行容器

12.進入web容器執行啟動腳本

sudo docker exec -it {web容器id} /bin/bash start.sh

13.數據導入

  • 這里我進入容器進行數據導入,當然也可以通過構建mysql的dockerfile去執行shell命令導入
#進入mysql 容器
docker exec -it {mysql容器id} /bin/bash
#登陸mysql
mysql -uroot -p你的密碼
# use到指定項目的庫
use west_coast
# 數據導入
source /opt/west_coast.sql
  • 最終訪問ip就可以啦!

---問題存在:

  • 連接數據庫粗在‘performance_schema.session_variables’ doesn’t exist問題。可進入構建mysql容器

    docker exec -it {mysql容器id} /bin/bash
    # 執行命令
    mysql_upgrade -u root -p --force
    # 輸入密碼,然后重啟mysql服務即可
    
  • 參考文獻:https://zhuanlan.zhihu.com/p/145364353


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM