python 我的Docker Alpine LAMP的Docker控制台
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python 我的Docker Alpine LAMP的Docker控制台相关的知识,希望对你有一定的参考价值。
#!/usr/bin/env python3
# TODO @ SL :: ask confirmation when removing sites or stopping server
import os
import sys
import shlex
import argparse
from subprocess import call, Popen, PIPE
APP_NAME = 'Docker Console'
APP_VERSION = '1.0'
CEND = '\33[0m'
CBOLD = '\33[1m'
CITALIC = '\33[3m'
CURL = '\33[4m'
CBLINK = '\33[5m'
CBLINK2 = '\33[6m'
CSELECTED = '\33[7m'
CBLACK = '\33[30m'
CRED = '\33[31m'
CGREEN = '\33[32m'
CYELLOW = '\33[33m'
CBLUE = '\33[34m'
CVIOLET = '\33[35m'
CBEIGE = '\33[36m'
CWHITE = '\33[37m'
CBLACKBG = '\33[40m'
CREDBG = '\33[41m'
CGREENBG = '\33[42m'
CYELLOWBG = '\33[43m'
CBLUEBG = '\33[44m'
CVIOLETBG = '\33[45m'
CBEIGEBG = '\33[46m'
CWHITEBG = '\33[47m'
CGREY = '\33[90m'
CRED2 = '\33[91m'
CGREEN2 = '\33[92m'
CYELLOW2 = '\33[93m'
CBLUE2 = '\33[94m'
CVIOLET2 = '\33[95m'
CBEIGE2 = '\33[96m'
CWHITE2 = '\33[97m'
CGREYBG = '\33[100m'
CREDBG2 = '\33[101m'
CGREENBG2 = '\33[102m'
CYELLOWBG2 = '\33[103m'
CBLUEBG2 = '\33[104m'
CVIOLETBG2 = '\33[105m'
CBEIGEBG2 = '\33[106m'
CWHITEBG2 = '\33[107m'
# user = os.environ['USER']
user = os.getuid()
if os.path.islink(__file__): # A symlink
root_dir = os.readlink(__file__)[:-int(len(os.path.basename(__file__)))] # Remove the filename to return the directory
else: # Not a symlink
root_dir = os.path.dirname(__file__)
vhosts_dir = os.path.join(root_dir, 'config', 'conf.d', 'vhosts')
def is_directory_valid():
docker_compose_file_yml = os.path.join(root_dir, 'docker-compose.yml')
docker_compose_file_yaml = os.path.join(root_dir, 'docker-compose.yaml')
if not os.path.exists(docker_compose_file_yml) and not os.path.exists(docker_compose_file_yaml):
print('Error: this script needs to be ran inside a directory with a `docker-compose.yml` or `docker-compose.yaml` file')
exit(1)
class DockerConsole(object):
# Init
def __init__(self):
parser = argparse.ArgumentParser(
description='Do some server stuff (this script adds some functionality to my docker-compose lamp)',
usage='''docker-console <command> [<subcommand>]
The command options are:
%sserver%s Start or stop the server
%svhost%s Add or remove a virtual host
''' % (CYELLOW, CEND, CYELLOW, CEND))
parser.add_argument('command', type=str, help='"%sserver%s / %svhost%s"' % (CYELLOW, CEND, CYELLOW, CEND), nargs='?')
args = parser.parse_args(sys.argv[1:2])
if not args.command or not hasattr(self, args.command):
print(CRED2 + 'Error: Unrecognized command\n' + CEND)
parser.print_help()
exit(1)
getattr(self, args.command)()
# Server
def start(self):
print(CYELLOW + 'Starting server...\n' + CEND)
cmd = 'docker-compose up -d'
p = Popen(shlex.split(cmd), stderr=PIPE, stdout=PIPE)
output = p.communicate()
if output[0]: # stdout
print(str(output[0], 'utf-8'))
if output[1]: # stderr
print(str(output[1], 'utf-8'))
# Check if need to chown
config_dir = os.path.join(root_dir, 'config')
html_dir = os.path.join(root_dir, 'html')
if os.stat(config_dir).st_uid != user or os.stat(config_dir).st_gid != user:
config_chown = True
else:
config_chown = False
if os.stat(html_dir).st_uid != user or os.stat(html_dir).st_gid != user:
html_chown = True
else:
html_chown = False
if config_chown:
cmd = 'sudo chown -R %s:%s ./config' % (user, user)
p = call(shlex.split(cmd))
if html_chown:
cmd = 'sudo chown -R %s:%s ./html' % (user, user)
p = call(shlex.split(cmd))
print(CGREEN + 'Started server!' + CEND)
def stop(self):
print(CYELLOW + 'Stopping server...\n' + CEND)
cmd = 'docker-compose stop'
p = Popen(shlex.split(cmd), stderr=PIPE, stdout=PIPE)
output = p.communicate()
if output[0]: # stdout
print(str(output[0], 'utf-8'))
if output[1]: # stderr
print(str(output[1], 'utf-8'))
print(CGREEN + 'Stopped server!' + CEND)
def restart(self):
self.stop()
self.start()
def server(self):
parser = argparse.ArgumentParser(
description='Start or stop the server',
usage='''docker-console server %s<option>%s
The server options are:
%sstart%s Start the server
%sstop%s Stop the server
%srestart%s Restart the server
''' % (CYELLOW, CEND, CYELLOW, CEND, CYELLOW, CEND, CYELLOW, CEND))
parser.add_argument('option', type=str, help='"%sstart%s / %sstop%s / %srestart%s"' % (CYELLOW, CEND, CYELLOW, CEND, CYELLOW, CEND), nargs='?')
args = parser.parse_args(sys.argv[2:])
if not args.option or not hasattr(self, args.option):
print(CRED2 + 'Error: Unrecognized subcommand\n' + CEND)
parser.print_help()
print('')
exit(1)
getattr(self, args.option)()
# Vhost
def list(self):
print('Sites on this server: ')
for i, site in enumerate(os.listdir(vhosts_dir)):
print(CYELLOW + ' %s.' % str(i + 1) + CEND + ' %s' % site)
def add(self):
print('Add a site to this server:')
print('\nUrl of the site:')
site_name = input(' %s>%s ' % (CBEIGE, CEND))
while not site_name.strip():
site_name = input(' %s>%s ' % (CBEIGE, CEND))
# TODO @ SL :: check if sitename already exists
print('\nSite alias? [%swww%s] (type `%sno%s` for empty)' % (CGREEN, CEND, CYELLOW, CEND))
site_alias = input(' %s>%s ' % (CBEIGE, CEND))
if not site_alias.strip():
site_alias = 'www'
if site_alias.strip().lower() == 'www':
site_alias = 'www'
if site_alias.strip().lower() == 'no':
site_alias = ''
else:
site_alias = site_alias.strip().lower()
if site_alias:
site_alias = site_alias + '.'
print('\nPort of the site: [%s80%s]' % (CGREEN, CEND))
site_port = input(' %s>%s ' % (CBEIGE, CEND))
if not site_port.strip():
site_port = '80'
if site_port.strip() == 80:
site_port = '80'
if not site_port.strip().isnumeric():
site_port = '80'
else:
site_port = str(site_port.strip())
print('\nShould the public root be in the `%spublic%s` directory? [%sY%s/%sn%s]' % (CYELLOW, CEND, CGREEN, CEND, CRED2, CEND))
public_dir = input(' %s>%s ' % (CBEIGE, CEND))
if not public_dir.strip():
public_dir = 'y'
if public_dir.strip().lower() == 'y':
public_dir = 'y'
else:
public_dir = 'n'
# Confirmation
print('\nPlease confirm to create the following site: [%sY%s/%sn%s]' % (CGREEN, CEND, CRED2, CEND))
print(' Site url %s: %s%s%s' % (CBLUE, CVIOLET, site_name, CEND))
print(' Site alias %s: %s%s%s' % (CBLUE, CVIOLET, site_alias, CEND))
print(' Site port %s: %s%s%s' % (CBLUE, CVIOLET, site_port, CEND))
print(' Public directory %s: %s%s%s' % (CBLUE, CVIOLET, public_dir, CEND))
confirm = input(' %s>%s ' % (CBEIGE, CEND))
if not confirm.strip():
confirm = 'y'
if confirm.strip().lower() == 'y':
confirm = 'y'
else:
confirm = 'n'
if confirm == 'y':
# Write file
file = os.path.join(vhosts_dir, site_name + '.conf')
fh = open(file, 'w')
fh.write('<VirtualHost *:%s>\n' % str(site_port))
fh.write(' ServerName %s\n' % site_name)
fh.write(' ServerAlias %s%s\n\n' % (site_alias, site_name))
if public_dir == 'y':
fh.write(' DocumentRoot /web/html/%s/public\n' % site_name)
else:
fh.write(' DocumentRoot /web/html/%s\n' % site_name)
fh.write('</VirtualHost>')
fh.close()
print(CGREEN + '\nAdded site: ' + site_name + CEND)
print(CVIOLET + '\nTo be able to access this site, please restart the server' + CEND)
def remove(self):
print('Remove a site from this server:')
print('\nType a name, or type `%slist%s` to choose from a list: ' % (CYELLOW, CEND))
remove_input = input(' %s>%s ' % (CBEIGE, CEND))
while not remove_input.strip():
remove_input = input(' %s>%s ' % (CBEIGE, CEND))
if remove_input.strip() == 'list':
sites = {}
for i, site in enumerate(os.listdir(vhosts_dir)):
sites[str(i + 1)] = site
print(CYELLOW + ' %s.' % str(i + 1) + CEND + ' %s' % site)
print('\nRemove site number: ')
site_number = input(' %s>%s ' % (CBEIGE, CEND))
while not site_number.strip():
site_number = input(' %s>%s ' % (CBEIGE, CEND))
if site_number not in sites:
print(CRED2 + '\nError: that site does not exist' + CEND)
exit(1)
file = os.path.join(vhosts_dir, sites[site_number])
os.remove(file) # TODO @ SL :: ask for confirmation first
print(CGREEN + '\nRemoved site: ' + sites[site_number] + CEND)
else:
file = os.path.join(vhosts_dir, remove_input.strip() + '.conf')
if not os.path.exists(file):
print(CRED2 + '\nError: that site does not exist' + CEND)
exit(1)
os.remove(file) # TODO @ SL :: ask for confirmation first
print(CGREEN + '\nRemoved site: ' + remove_input.strip() + '.conf' + CEND)
def vhost(self):
if not os.path.exists(vhosts_dir):
os.mkdir(vhosts_dir)
parser = argparse.ArgumentParser(
description='Add or remove a virtual host',
usage='''docker-console vhost %s<option>%s
The vhost options are:
%slist%s List all virtual hosts
%sadd%s Add a virtual host
%sremove%s Remove a virtual host
''' % (CYELLOW, CEND, CYELLOW, CEND, CYELLOW, CEND, CYELLOW, CEND))
parser.add_argument('option', type=str, help='"%slist%s / %sadd%s / %sremove%s"' % (CYELLOW, CEND, CYELLOW, CEND, CYELLOW, CEND), nargs='?')
args = parser.parse_args(sys.argv[2:])
if not args.option or not hasattr(self, args.option):
print(CRED2 + 'Error: Unrecognized subcommand\n' + CEND)
parser.print_help()
print('')
exit(1)
getattr(self, args.option)()
if __name__ == '__main__':
print('\n' + CBEIGE + '[ ' + CVIOLET + APP_NAME + CBLUE + ' v' + APP_VERSION + CBEIGE + ' ]' + CEND + '\n')
# Check if there is a docker-compose file in this directory.
is_directory_valid()
try:
DockerConsole()
except KeyboardInterrupt:
print('\n')
sys.exit(0)
print('')
以上是关于python 我的Docker Alpine LAMP的Docker控制台的主要内容,如果未能解决你的问题,请参考以下文章
Alpine makes Python Docker builds 50× slower, and images 2× larger
将 bcrypt 添加到 package.json 时,如何使用 docker node alpine Image 解决“找不到任何要使用的 Python 安装”?
docker在alpine linux中构建python django应用程序时出错
Sanic over alpine:latest(3.9) 的 Docker 镜像使用 python json 而不是 ujson