I'm Docker, and I'm happy!
試圖用網頁建立 Container 然後成功ㄌ!
- About the Project
- Feature
- Package Used
- Easy Start with docker-compose
- Getting start with your own server
- Prerequisites
- 工作分配
- 特別感謝
- 未來展望
- Reference
-
點選
Runnnn it !
跳轉頁面並輸入欲執行的指令 -
Stop
Container
- Run a Container through web
- show information of the container you've just build sucessfully
- pull image (
Dockerhub
) if the image haven't pulled - shell escape for some unsecure string
- execute some instruction in Container
- shell escape
- Stop specific container by name of the container
- shell escape
- python3 3.6.9
- shellescape
- pipenv
- django 3.0.3
- Docker
- curl
git clone https://github.com/TristaRin/happyDocker.git
cd prinsis/
visit: http://127.0.0.1:8000/manageDocker/manage Then you can see the main page of our project
- Enter remote server
ssh 帳號@遠端ip
- prepare all packages
sudo apt install python3-pip
pip3 install pipenv
- clone project
git clone https://github.com/TristaRin/happyDocker.git
- in your project folder, and enter the virtual environment. install django
cd happyDocker/
python3 -m pipenv shell
pip3 install django==3.0.3
- runserver
cd prinsis/
python manage.py migrate
python manage.py runserver ip:port
-
localhost 佈署
請先確認 python3 版本3.6.9 然後安裝一些管理套件
sudo apt install python3-pip pip3 install pipenv
-
在本地端建好專案~ 先建一個資料夾叫 對此資料夾創建(或進入)虛擬環境 再裝個 django
mkdir happyDocker cd happyDocker/ python3 -m pipenv shell pip3 install django==3.0.3
建一個 django 專案叫 prinsis
django-admin startproject prinsis
進入專案、匯入 django sql 、(建管理員)
cd prinsis/ python manage.py migrate (python manage.py createsuperuser)
若要讓專案可以跑在遠端伺服器上要改一下這個檔案
cd prinsis/ vim settings.py
ALLOWED_HOSTS = ['163.22.17.137', 'localhost', '127.0.0.1']
-
localhost 可以看小火箭了
cd .. python manage.py runserver
(注意)請確認你是在虛擬環境中,若不再虛擬環境中runserver會錯誤
-
終於可以來新增一個 app 了~ 在 /happyDocker/prinsis 底下建一個 app 叫 manageDocker
python manage.py startapp manageDocker
修改 /happyDocker/prinsis/prinsis 底下的 setting.py
cd prinsis/ vim setting.py
INSTALLED_APPS = [ ... 'manageDocker', ]
在 /happyDocker/prinsis 底下建一個資料夾叫 templates
cd .. mkdir templates
修改 /happyDocker/prinsis/prinsis 底下的 setting.py
cd prinsis/ vim setting.py
TEMPLATES = [ { ..., 'DIRS': [ os.path.join(BASE_DIR, 'templates'), ], ... } ]
LANGUAGE_CODE = 'zh-hant' TIME_ZONE = 'Asia/Taipei' USE_I18N = True USE_L10N = True USE_TZ = False
修改 /happyDocker/prinsis/prinsis 底下的 urls.py
vim urls.py
from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('manageDocker/',include('manageDocker.urls')), ]
-
在這 app 裡面寫些 api
- 在 /happyDocker/prinsis/manageDocker 底下建一個 urls.py
cd .. cd manageDocker/ vim urls.py
from django.urls import path, include from . import views from django.conf.urls import url urlpatterns = [ path('hello_world',views.hello_world), url('manage', views.manage), ]
- 在 /happyDocker/prinsis/templates 底下創一個 hello_world.html 和 manage.html
cd .. cd templates/ vim hello_world.html
<!DOCTYPE html> <html> <head> <title></title> </head> <body> Hello World </body> </html>
vim manage.html
(補充)我是用 bootstrap 的 範例頁面 怎麼用 bootstrap 請參考這
<!doctype html> <html lang="en"> <head> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"><link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="description" content=""> <meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors"> <meta name="generator" content="Jekyll v4.0.1"> <title>Checkout example · Bootstrap</title> <style> .bd-placeholder-img { font-size: 1.125rem; text-anchor: middle; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } @media (min-width: 768px) { .bd-placeholder-img-lg { font-size: 3.5rem; } } </style> <!-- Custom styles for this template --> <link href="form-validation.css" rel="stylesheet"> </head> <body class="bg-light"> <div class="container"> <div class="py-5 text-center"> <img class="d-block mx-auto mb-4" src="/docs/4.5/assets/brand/bootstrap-solid.svg" alt="" width="72" height="72"> <h2>Build your docker</h2> <p class="lead">This is a happyDocker! Which makes you happy?</p> </div> <div class="row"> <div class="col-md-4 order-md-2 mb-4"> <h4 class="d-flex justify-content-between align-items-center mb-3"> <span class="text-muted">container info</span> <span class="badge badge-secondary badge-pill">{{status}}</span> </h4> <ul class="list-group mb-3"> <li class="list-group-item d-flex justify-content-between lh-condensed"> <div> <h6 class="my-0"> id</h6> </div> <span class="text-muted">{{id}}</span> </li> <li class="list-group-item d-flex justify-content-between lh-condensed"> <div> <h6 class="my-0">image file</h6> </div> <span class="text-muted">{{image}}</span> </li> <li class="list-group-item d-flex justify-content-between lh-condensed"> <div> <h6 class="my-0">command</h6> </div> <span class="text-muted">{{command}}</span> </li> <li class="list-group-item d-flex justify-content-between lh-condensed"> <div> <h6 class="my-0">name</h6> </div> <span class="text-muted">{{name}}</span> </li> </ul> </div> <div class="col-md-8 order-md-1"> <h4 class="mb-3">Input</h4> <form class="needs-validation" novalidate action="manage" method="post">{% csrf_token %} <div class="col-md-6 mb-3"> <label for="firstName">image</label> <input type="text" class="form-control" id="image" name="image" placeholder="" value="" required> <div class="invalid-feedback"> Valid first name is required. </div> </div> <div class="col-md-6 mb-3"> <label for="firstName">command</label> <input type="text" class="form-control" id="command" name="command" placeholder="" value="" required> <div class="invalid-feedback"> Valid first name is required. </div> </div> <hr class="mb-4"> <button class="btn btn-primary btn-lg btn-block" type="submit">Build it!</button> </form> </div> </div> <footer class="my-5 pt-5 text-muted text-center text-small"> <p class="mb-1">© 2020-06-18 prinsis</p> </footer> </div> </body> </html>
(補充) django 規定在 form 後面加要 token
{% csrf_token %}
- 在 server 上架 Docker engine docker 安裝參考
- Update the apt package index and install packages to allow apt to use a repository over HTTPS:
$ sudo apt-get update
$ sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common
- Add Docker’s official GPG key:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo apt-key fingerprint 0EBFCD88
- Use the following command to set up the stable repository. To add the nightly or test repository, add the word nightly or test (or both) after the word stable in the commands below. Learn about nightly and test channels.
sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
- install Docker egine
- Update the apt package index, and install the latest version of Docker Engine and containerd, or go to the next step to install a specific version:
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io
-
To install a specific version of Docker Engine, list the available versions in the repo, then select and install:
a. List the versions available in your repo:
apt-cache madison docker-ce
b. Verify that Docker Engine is installed correctly by running the hello-world image.
- 權限問題 使每次執行 docker 時不用加 sudo
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post http://%2Fvar%2Frun%2Fdocker.sock/v1.40/images/create?fromImage=ubuntu&tag=latest: dial unix /var/run/docker.sock: connect: permission denied
-
Create the docker group.
sudo groupadd docker
-
Add your user to the docker group.
sudo usermod -aG docker ${USER}
-
logout
cd prinsis/manageDocker/
vim view.py
- 將前端資料 POST 到後端
if request.POST:
# 拿到計算所需的參數
# POST 的 key 為 tag 中的 name
image = request.POST['image']
command = request.POST['command']
- 確認 image 是否已存在
Docker 相關指令:
- (CMD 指令)使用
curl
以及docker.sock
socket檔抓取 image 的 json 資料
curl --unix-socket /var/run/docker.sock http:/v1.24/images/json
- pull image
- 須為存在在 dockerhub 上的 image
docker pull <image_name>
- 快速刪除存在
<none>
的特定 image
docker images -f "dangling=true" -q
使用 python 執行 command line 指令:
os.system(<command>) # 執行指令
os.popen(<command>).readlines() # 每行讀取 CMD 的 stdout
處理 json
檔:
import json
<list> = json.loads(<data>)
實際實做範例:
check_images = False
images_json = os.popen('curl --unix-socket /var/run/docker.sock http:/v1.24/images/json').readlines()[0]
images_list = json.loads(images_json.strip())
try:
# list 中為 dictionary
for each_image_dict in images_list:
# RepoTags 為紀錄 image 的 key
if image in each_image_dict['RepoTags']:
check_images = True
break
except TypeError:
# 處理 <none> 問題
os.system('docker images -f "dangling=true" -q')
for each_image_dict in images_list:
if image in each_image_dict['RepoTags']:
check_images = True
break
if check_images == False:
os.system('docker pull '+image)
- 依據 POST 回來的資訊 build Container
此專案將建立的 Container 放背景執行
不建議使用
-idt
(CMD) 建立 Container
docker run -idt <image> <command>
實際範例並抓取回傳的 Container id
:
build_cmd = "docker run -idt "+ image+ " "+ command
tmp = os.popen(build_cmd).readlines()[0]
tmp_deal = tmp.strip()
- 抓取 Container name (CMD)抓取 Container name 使用:
docker ps -a | grep "<Container_id>"
實際範例程式:
# 抓取 11 位 id
id_cmd = tmp_deal[0:12]
# 讀取回傳資料後最後一項為 Container name
search = os.popen('docker ps -a | grep "'+ id_cmd +'"').readlines()[0]
search_name = search.split()[-1]
- 將 Container 資料使用 render 渲染回網頁
try:
ctx['image'] = image
ctx['command'] = command
ctx['name'] = search_name
ctx['id'] = id_cmd
ctx['status'] = 'Success'
except:
ctx['image'] = image
ctx['command'] = command
ctx['name'] = ''
ctx['id'] = ''
ctx['status'] = 'Fail'
return render(request, "manage.html", ctx)
- 將以上專案 push 到 github 上
- 在遵循 Getting start with your own server 的步驟即可
- 小公主:Django 架設,manage.html 前端,Server 申請
- 姊姊:Docker 建立,views.py (後端), reaction.html 前後端,Dockerfile 與 docker compose
😄 BlueT, 守恩, 果子維, 王威, 逸于, 丁丁, 許家瑋
增加 停止/執行 特定 Container 的功能- Container 建立時的參數增加
- 能夠定時清理使用不到的 Container
- 可以更改 Container 名字
- port
- python http client
LSA不會被當
- 守恩的筆記
- https://getbootstrap.com/
- https://docs.docker.com/engine/api/sdk/examples/
- https://docs.docker.com/engine/install/ubuntu/
- https://docs.docker.com/engine/reference/commandline/container_prune/
- https://forums.docker.com/t/how-to-remove-none-images-after-building/7050/2
- https://codertw.com/%E7%A8%8B%E5%BC%8F%E8%AA%9E%E8%A8%80/80195/
- https://pypi.org/project/shellescape/