Проект «SnakeProject» Михаила КозловаРегистрация

Навигация
⇒FreeBSD and Nix⇒

⇐CISCO
⇐Voice(Asterisk\Cisco)
⇐Microsoft
⇐Powershell
⇐Python
⇐SQL\T-SQL
⇐1С
⇐Общая
⇐WEB Разработка
⇐ORACLE SQL \ JAVA
⇐Мото

Docker: Flask + uWSGI простое приложение


 

Docker: Flask + uWSGI простое приложение


Создадим папку для проекта:
mkdir -p /data/docker/app && cd /data/docker


Простейше приложение flask:
vi app/start.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
  return 'Test content\n'
if __name__ == '__main__':
  app.run(debug=True, host='0.0.0.0')


Файл образа:
vi Dockerfile
FROM python:3.6
RUN pip install Flask
WORKDIR /app
COPY app /app
CMD ["python", "start.py"]


Собираем образ с именем flaskapp:
docker build -t flaskapp .


Запускаем контейнер на основе собранного образа:
docker run -d -p 80:5000 flaskapp


Проверяем:
curl localhost:80
Test content


Теперь смонтируем каталог как том (формат: -v HOST_DIR:CONTAINER_DIR)
Это нужно для того, чтоб вносимые изменения в контейнере сохранялись


Остановим последний запущенный контейнер:
docker stop $(docker ps -lq)
731f6af63293


Удалим его:
docker rm $(docker ps -lq)
731f6af63293


Запусти образ с подмонтированным томом:
docker run -d -p 80:5000 -v "$(pwd)"/app:/app flaskapp


Проверяем:
curl localhost:80
Test content


Поменяем возвращаемую строку:
sed -i s/content/new_content/ app/start.py


Проверяем:
curl localhost:80
Test new_content

 

Запуск приложения Flask через uWSGI


Остановим и удалим контейнер:
docker stop $(docker ps -lq) && docker rm $(docker ps -lq)


Переделаем приложение под uWSGI:
vi Dockerfile
FROM python:3.6
RUN pip install Flask uWSGI
WORKDIR /app
COPY app /app
CMD ["uwsgi", "--http", "0.0.0.0:80", "--wsgi-file", "/app/start.py", \
    "--callable", "app", "--stats", "0.0.0.0:81"]


Собираем:
docker build -t uwsgiapp .


Запускаем:
docker run -d -p 80:80 -p 81:81 uwsgiapp


Проверяем:
curl localhost:80
Test new_content


curl localhost:81
        "version":"2.0.17.1",
        "listen_queue":0,
        "listen_queue_errors":0,
        "signal_queue":0,
        "load":0,
        "pid":1,
        "uid":0,
        "gid":0,
        "cwd":"/app",
        "locks":[
...
}


Контейнер по умолчание стартует из под root все процессы:
docker ps
CONTAINER ID  IMAGE     COMMAND                  PORTS                     
212f91cb9626     uwsgiapp  "uwsgi --http 0.0.0.…"   0.0.0.0:80-81->80-81/tcp


docker logs 212f91cb9626
*** Starting uWSGI 2.0.17.1 (64bit) on [Tue Feb  5 13:36:39 2019] ***
compiled with version: 6.3.0 20170516 on 05 February 2019 13:36:17
os: Linux-3.10.0-862.el7.x86_64 #1 SMP Fri Apr 20 16:44:24 UTC 2018
nodename: 212f91cb9626
machine: x86_64
clock source: unix
pcre jit disabled
detected number of CPU cores: 4
current working directory: /app
detected binary path: /usr/local/bin/uwsgi
uWSGI running as root, you can use --uid/--gid/--chroot options
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) ***
your memory page size is 4096 bytes
detected max file descriptor number: 65536
lock engine: pthread robust mutexes
thunder lock: disabled (you can enable it with --thunder-lock)
uWSGI http bound on 0.0.0.0:80 fd 4
uwsgi socket 0 bound to TCP address 127.0.0.1:39899 (port auto-assigned) fd 3
uWSGI running as root, you can use --uid/--gid/--chroot options
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) ***
Python version: 3.6.8 (default, Jan 23 2019, 02:38:10)  [GCC 6.3.0 20170516]
*** Python threads support is disabled. You can enable it with --enable-threads ***
Python main interpreter initialized at 0x561489b0b6b0
uWSGI running as root, you can use --uid/--gid/--chroot options
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) ***
your server socket listen backlog is limited to 100 connections
your mercy for graceful operations on workers is 60 seconds
mapped 145840 bytes (142 KB) for 1 cores
*** Operational MODE: single process ***
WSGI app 0 (mountpoint='') ready in 0 seconds on interpreter 0x561489b0b6b0 pid: 1 (default app)
uWSGI running as root, you can use --uid/--gid/--chroot options
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) ***
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI master process (pid: 1)
spawned uWSGI worker 1 (pid: 7, cores: 1)
*** Stats server enabled on 0.0.0.0:81 fd: 12 ***
spawned uWSGI http 1 (pid: 8)
[pid: 7|app: 0|req: 1/1] 172.17.0.1 () {28 vars in 288 bytes} [Tue Feb  5 13:36:48 2019]

GET / => generated 17 bytes in 2 msecs (HTTP/1.1 200) 2 headers in 79 bytes (1 switches on core 0)
[pid: 7|app: 0|req: 2/2] 10.0.2.2 () {40 vars in 736 bytes} [Tue Feb  5 13:39:21 2019]

GET / => generated 17 bytes in 1 msecs (HTTP/1.1 200) 2 headers in 79 bytes (1 switches on core 0)

 

Запуск приложения через скрипт


vi app/start.py
from flask import Flask

app = Flask(__name__)
@app.route('/')

def hello_world():
  return 'Test new_content\n'

if __name__ == '__main__':
  app.run(debug=True, host='0.0.0.0', port=5000)

 

vi Dockerfile
FROM python:3.6

RUN pip install Flask uWSGI

WORKDIR /app

COPY app /app
COPY cmd.sh /

EXPOSE 80 81

CMD ["/cmd.sh"]

 

В скрипте будет два варианта запуска для разработчиков и на бой:
vi cmd.sh
#!/bin/bash
set -e
if [ "$ENV" = 'DEV' ]; then
  echo "Running Development Server"
  exec python "start.py"
else
  echo "Running Production Server"
  exec uwsgi --http 0.0.0.0:80 --wsgi-file /app/start.py \
             --callable app --stats 0.0.0.0:81
fi

 

docker build -t uwsgiapp .

docker run -e "ENV=DEV" -p 80:5000 uwsgiapp

docker run -p 80:80 -p 81:81 uwsgiapp

 

Сборка с помощью docker-compose


По сути build тут указывает на наш каталог, а точнее на Dockerfile
vi docker-compose.yml
uwsgiapp:
  build: .
  ports:
    - "5000:5000"
  environment:
    ENV: DEV
  volumes:
    - ./app:/app


Запускаем и проверяем для dev:
docker-compose up
docker-compose -f docker-compose.yml up

curl localhost:5000


Запускаем и проверяем для production:
cp docker-compose.yml docker-compose-prod.yml
vi docker-compose-prod.yml
uwsgiapp:
  build: .
  ports:
    - "80:80"
    - "81:81"
  volumes:
    - ./app:/app


docker-compose -f docker-compose-prod.yml up

curl localhost:80
Test new_content

 


Запуск от другого пользователя


Добавим группу и пользователя
После USER все будет отрабатывать от имени учетной записи uwsgi
cat Dockerfile
FROM python:3.4

RUN groupadd -r uwsgi && useradd -r -g uwsgi uwsgi
RUN pip install Flask uWSGI
WORKDIR /app
COPY app /app
COPY cmd.sh /

EXPOSE 9000 9001
USER uwsgi

CMD ["/cmd.sh"]

 

cat cmd.sh
#!/bin/bash
echo "Running Production Server"
exec uwsgi --http 0.0.0.0:9000 --wsgi-file /app/start.py \
           --callable app --stats 0.0.0.0:9001

 

Для продакшна:
cat docker-compose.yml
uwsgiapp:
  build: .
  ports:
   - "9000:9000"
   - "9001:9001"
  volumes:
    - ./app:/app

 

Или для теста:
uwsgiapp:
  build: .
  ports:
   - "5000:5000"
  environment:
    ENV: DEV
  volumes:
    - ./app:/app

 


Модульные тесты


Создадим простой тест, который проверяет код возвращаемой страницы:
vi app/tests.py
import unittest
import start

class TestCase( unittest.TestCase ):
    def setUp( self ):
        start.app.config["TESTING"] = True
        self.app = start.app.test_client()
    def test_get_mainpage( self ):
        page = self.app.get( "/" )
        assert page.status_code == 200
        assert 'new_content' in str( page.data )

if __name__ == '__main__':
    unittest.main()


Соберем и проверим:
docker build -t uwsgiapp .

docker run uwsgiapp python tests.py
.
----------------------------------------------------------------------
Ran 1 test in 0.015s

OK

 

А теперь добавим его в стартовый скрипт cmd.sh:
vi cmd.sh
#!/bin/bash
set -e
if [ "$ENV" = 'DEV' ]; then
  echo "Running Development Server"
  exec python "start.py"
elif [ "$ENV" = 'UNIT' ]; then
  echo "Running Unit Tests"
  exec python "tests.py"
else
  echo "Running Production Server"
  exec uwsgi --http 0.0.0.0:80 --wsgi-file /app/start.py \
             --callable app --stats 0.0.0.0:81
fi


Соберем и проверим:
docker build -t uwsgiapp .


docker run -e ENV=UNIT uwsgiapp
Running Unit Tests
.
----------------------------------------------------------------------
Ran 1 test in 0.015s

OK

 


Комментарии пользователей

Эту новость ещё не комментировалиНаписать комментарий
Анонимам нельзя оставоять комментарии, зарегистрируйтесь!

© Snakeproject.ru создан в 2013 году. При копировании материала с сайта - оставьте ссылку.


Яндекс.Метрика

Goon Каталог сайтов Рейтинг@Mail.ru