整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

python学习笔记(基本语法+脚本)

本语法

1. 简单控制语句

字符串推荐用'' 单引号引用

list: List[int] = [1, 2, 3]
for elem in list:
    if elem > 1:
        print(f'data {elem} > 1')  # 这里是format语句,属于语法糖
    else:
        print(f'data {elem} < 1')

'''
data 1 < 1
data 2 > 1
data 3 > 1
'''

2. 异常

x = -1
try:
    if x < 0:
        raise Exception("Sorry, no numbers below zero")
except Exception as err:
    print("find err: %s" % err)
'''
find err: Sorry, no numbers below zero
''' 

3. 推导式(比较晦涩难懂)

  • 参考: https://www.cnblogs.com/desireyang/p/12160332.html

推导式好处: 效率更高,底层是c执行

1. 列表推导式

一共两种形式:(参考: https://zhuanlan.zhihu.com/p/139621170) , 它主要是输出是列表(list)

  • [xforxindataifcondition] 这里的含义是data只有满足if条件中的情况才保留 (if)
  • [exp1ifconditionelseexp2forxindata] , 这里的含义是data满足if条件时执行exp1 否则 exp2 (if - else)
import re

"""
获取所有的数字
"""
list = ["1", "2", "3", "4", "5", "a", "b", "c"]
print([elem for elem in list if re.match("\\d", elem)])
'''
['1', '2', '3', '4', '5']
'''

"""
获取所有的字母
"""
print([elem for elem in list if re.match("[a-z]", elem)])
'''
['a', 'b', 'c']
'''

"""
如果元素是数字则存储,否则则upper
"""
print([elem if re.match("\\d", elem) else elem.upper() for elem in list])
'''
['1', '2', '3', '4', '5', 'A', 'B', 'C']
'''

最佳实践: 参考(https://github.com/httpie/httpie/blob/master/httpie/core.py#L235)

def decode_raw_args(
        args: List[Union[str, bytes]],
        stdin_encoding: str
) -> List[str]:
    """
    Convert all bytes args to str
    by decoding them using stdin encoding.

    """
    return [
        arg.decode(stdin_encoding)
        if type(arg) is bytes else arg
        for arg in args
    ]


def decode_raw_args_parse(
        args: List[Union[str, bytes]],
        stdin_encoding: str
) -> List[str]:
    """
    Convert all bytes args to str
    by decoding them using stdin encoding.
    不使用推导式
    """
    result: List[str] = []
    for arg in args:
        if type(arg) is bytes:
            result.append(arg.decode(stdin_encoding))
        else:
            result.append(arg)
    return result


# arg.decode(stdin_encoding) if type(arg) is bytes else arg for arg in args
print(decode_raw_args(args=[b'111', b'222'], stdin_encoding="utf-8"))
print(decode_raw_args(args=["111", "222"], stdin_encoding=""))
'''
['111', '222']
['111', '222']
'''

print(decode_raw_args_parse(args=[b'111', b'222'], stdin_encoding="utf-8"))
print(decode_raw_args_parse(args=["111", "222"], stdin_encoding=""))
'''
['111', '222']
['111', '222']
'''

2. 字典推导式

{key_expr:value_exprforvalueincollectionifcondition} ,输出是dict

"""
{ key_expr: value_expr for value in collection if condition }

反转key value,且获取 value 为在set {'a', 'b', 'c'}中的元素
"""
dict_old = {'a': 'A', 'b': 'B', 'c': 'C', 'd': 'D'}
print({dict_old[value]: value for value in dict_old if value in {'a', 'b', 'c'}})
'''
{'A': 'a', 'B': 'b', 'C': 'c'}
'''

print({key: value for value, key in dict_old.items() if value in {'a', 'b', 'c'}})
'''
{'A': 'a', 'B': 'b', 'C': 'c'}
'''

3. 集合推导式

表达式:

  • {exprforvalueincollectionifcondition}
  • {exp1ifconditionelseexp2forxindata}输出是set

其实就是上面列表推导式[] 换成{} ,输出由list 变成了set

4. for 循环 迭代器

import os
from collections.abc import Iterable

with open("text.log", "wt") as file:
    file.truncate()
    file.writelines("line 1" + os.linesep)
    file.writelines("line 2" + os.linesep)
    file.writelines("line 3" + os.linesep)
    pass

with open("text.log", "rt") as file:
    for line in file:
        print("type: {type}, isinstance: {isinstance}, line: {line}".format(type=type(file),
                                                                            isinstance=isinstance(file, Iterable),
                                                                            line=line))
    pass

'''
type: <class '_io.TextIOWrapper'>, isinstance: True, line: line 1

type: <class '_io.TextIOWrapper'>, isinstance: True, line: line 2

type: <class '_io.TextIOWrapper'>, isinstance: True, line: line 3
'''

这里面_io.TextIOWrapper 实现了 __next__() 方法

比如我们自己实现一个可迭代的对象

下面可以看到我使用了类型申明List[str] 其实这个python运行时并不会检测,需要工具进行检测!

变量默认都是Any 类型 ,具体可以看 https://docs.python.org/zh-cn/3/library/typing.html

from typing import List

class Items(object):
    def __init__(self, list: List[str]):
        self.list = list
        self.index = 0

    def __next__(self, *args, **kwargs):
        """
        next,没有抛出StopIteration
        """
        if self.index >= len(self.list):
            raise StopIteration
        result = self.list[self.index]
        self.index = self.index + 1
        return result

    def __iter__(self, *args, **kwargs):
        """
        返回一个迭代器
        """
        return self


data = Items(["1", "2", "3"])

for x in data:
    print(x)
'''
1
2
3
'''

5. 包管理

from ..a import foo  # 上级目录
from .a import foo_a  # 当前目录

import sys  # 引用源码或者lib
from copy import deepcopy  # 引用源码或者lib

from pygments.formatters.terminal import TerminalFormatter  # 引用 lib.lib.file

import demo.utils.a


def c_foo():
    demo.utils.a.foo_a()
    TerminalFormatter()
    deepcopy()
    print(sys.api_version)


def b_foo():
    foo()

基本数据类型

1. 定义方式

  • mylist:list[str]=["apple","banana","cherry"]
  • mylist=["apple","banana","cherry"]

Text Type:

str

Numeric Types:

int,float,complex

Sequence Types:

list,tuple,range

Mapping Type:

dict

Set Types:

set,frozenset

Boolean Type:

bool

Binary Types:

bytes,bytearray,memoryview

2. 数字基本类型

x = 1  # int
y = 1.1  # float
z = 1j  # 复数(complex)
a = complex(1, 2)  # 复数(complex)
print(type(x))
print(type(y))
print(type(z))
print(z.imag, z.real)
print(type(a))
print(a.imag, a.real)
'''
<class 'int'>
<class 'float'>
<class 'complex'>
1.0 0.0
<class 'complex'>
2.0 1.0
'''

3. 字符串

str = "hello"
print(str)
print(str[0:])
print(str[:5])
print(str[:-1])
print(str[0:5])
print(str[0:5:1])
print(str[0:5:2])
'''
hello
hello
hello
hell
hello
hello
hlo
'''

# format
print("My name is {} and age is {}".format("tom", 18))
'''
My name is tom and age is 18
'''

quantity = 3
itemno = 567
price = 49.95
myorder = "I want to pay {2} dollars for {0} pieces of item {1}."
print(myorder.format(quantity, itemno, price))
'''
I want to pay 49.95 dollars for 3 pieces of item 567.
'''

# func
str = "hello world! "
print(str.upper())
print(str.lower())
print(str.strip())
print(str + " ...")
'''
HELLO WORLD! 
hello world! 
hello world!
hello world!  ...
'''

# format
myorder = "I have a {carname}, it is a {model}."
print(myorder.format(carname="Ford", model="Mustang"))
'''
I have a Ford, it is a Mustang.
'''

4. lambda

其实就是一个func

def add(num):
    return lambda x: x + num


print(add(10)(10))
'''
20
'''

lanbda 例子2

import json

class Obj:
    def __init__(self):
        self.name = "tom"
        self.age = 1


print(json.dumps(Obj(), default=lambda obj: obj.__dict__))
'''
{"name": "tom", "age": 1}
'''

集合

list,tuple,range,dict,set,frozenset

  • list , 例如:mylist=["apple","banana","cherry"]
  • tuple 是特殊的数组,就是不能改变, 例如mytuple=("apple","banana","cherry")
  • range 可以理解是个迭代器, 例如:
  • dict 就是个map, 例如:thisdict={"brand":"Ford","model":"Mustang","year":1964}
  • set 就是个去重复的list , 例如:myset={"apple","banana","cherry"}

1. list

mylist = ["apple", "banana", "cherry"]

# 切片
print(mylist[0])
print(mylist[2])
print(mylist[-1])
print(mylist[0:3:2])
'''
apple
cherry
cherry
['apple', 'cherry']
'''

# 基本操作
mylist.append("orange")
print(mylist)
'''
['apple', 'banana', 'cherry', 'orange']
'''

mylist.insert(0, "mango")
print(mylist)
'''
['mango', 'apple', 'banana', 'cherry', 'orange']
'''

# 循环
for x in mylist:
    print(x)

'''
apple
banana
cherry
orange
'''

for index in range(len(mylist)):
    print("index: %d" % index)
'''
index: 0
index: 1
index: 2
index: 3
index: 4
'''

if "apple" in mylist:
    print("success!")

'''
success!
'''

# [执行表达式(也就是for循环中的,如果有if则是if中执行的), for item in list 条件表达式]
new_list = [elem.upper() for elem in mylist if "a" in elem]  # contains 'a' char elem str
print(new_list)
'''
['MANGO', 'APPLE', 'BANANA', 'ORANGE']
'''

newList = []
for elem in mylist:
    if 'a' in elem:
        newList.append(elem.upper())
print(newList)
'''
['MANGO', 'APPLE', 'BANANA', 'ORANGE']
'''

2. map

thisdict = {"brand": "Ford", "model": "Mustang", "year": 1964}

for key, value in thisdict.items():
    print("key: {}, value: {}".format(key, value))

'''
key: brand, value: Ford
key: model, value: Mustang
key: year, value: 1964
'''

for key in thisdict:
    print("key: {}, value: {}".format(key, thisdict[key]))
'''
key: brand, value: Ford
key: model, value: Mustang
key: year, value: 1964
'''

3. range

# range 会生成一个迭代器,(start,end,sep) , 左闭右开
for x in range(6):  # [0,1,2,3,4,5]
    print("x is %d" % x)
'''
x is 0
x is 1
x is 2
x is 3
x is 4
x is 5
'''

for x in range(2, 6):
    print("x is %d" % x)

'''
x is 2
x is 3
x is 4
x is 5
'''

for x in range(1, 6, 2):
    print("x is %d" % x)
'''
x is 1
x is 3
x is 5
'''

方法

1. 定义一个空方法

def func_1():
    pass  # 空方法必须申明pass


func_1()

2. 参数

# name 为必须添的参数,不然为空会报错
# age 为默认参数
# agrs 为可变参数
# kwargs 为 k v 参数
def func_1(name, age=1, *args, **kwargs):
    print("name: %s" % name)
    print("age: %d" % age)
    print("len(args): {}, type: {}".format(len(args), type(args)))
    for value in args:
        print("args value: {}".format(value))

    print("len(kwargs): {}, type: {}".format(len(kwargs), type(kwargs)))
    for key, value in kwargs.items():
        print("kwargs key: {}, value: {}".format(key, value))


func_1(name="tom", age=10, args="1", kwargs="2")
'''
name: tom
age: 10
len(args): 0
len(kwargs): 0, type: <class 'tuple'>
len(kwargs): 2, type: <class 'dict'>
kwargs key: args, value: 1
kwargs key: kwargs, value: 2
'''

# 这里注意由于dict所以不能申明kv
func_1("tom", 10, "1", "2", args="1", kwargs="2")
'''
name: tom
age: 10
len(args): 2, type: <class 'tuple'>
args value: 1
args value: 2
len(kwargs): 2, type: <class 'dict'>
kwargs key: args, value: 1
kwargs key: kwargs, value: 2
'''

3. 类型

申明输入输出类型

from typing import List, Union
def decode_raw_args(
    args: List[Union[str, bytes]],
    stdin_encoding: str
) -> List[str]:
    """
    Convert all bytes args to str
    by decoding them using stdin encoding.

    """
    return [
        arg.decode(stdin_encoding)
        if type(arg) is bytes else arg
        for arg in args
    ]

1. 定义类和方法

# 如果没有父类继承,这里选择 object,比较规范
class Person(object):
    # gender none, male or female
    gender = "none"

    # 构造器
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def my_name(self):
        return self.name


p = Person(name="tome", age=1)
print(p.my_name())

2. 类型的继承

import json


class Person(object):
    # gender none, male or female
    gender = "none"

    # 构造器
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def my_name(self):
        return self.name


p = Person(name="tome", age=1)
print(p.my_name())


class Mail(Person):
    def __init__(self, name, age):
        super(Mail, self).__init__(name, age)
        self.gender = "mail"

    def my_name(self):
        return self.name + "_mail"


p = Mail(name="tome", age=1)
print(json.dumps(p, default=lambda obj: obj.__dict__))
print(p.my_name())

3. 类__new__函数

主要是__init__执行前会调用

#!/usr/bin/python

import json


class Person(object):
    def __new__(cls, *args, **kwargs):
        instance = object.__new__(cls)
        instance.job = "it"
        return instance

    # construct
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def to_json(self):
        return json.dumps(self, default=lambda obj: obj.__dict__)


p = Person(name="tome", age=1)
print(p.to_json()) # {"age": 1, "job": "it", "name": "tome"}

其他用法技巧

1. 断言

if type(1) is int:
    print("args is int")
    ...  # 等效 pass
'''
args is int
'''

2. 测试<<<

可以参考文件: https://segmentfault.com/q/1010000010389542 , 属于doctest

def humanize_bytes(n, precision=2):
    # Author: Doug Latornell
    # Licence: MIT
    # URL: https://code.activestate.com/recipes/577081/
    """Return a humanized string representation of a number of bytes.

    >>> humanize_bytes(1)
    '1 B'
    >>> humanize_bytes(1024, precision=1)
    '1.0 kB'
    >>> humanize_bytes(1024 * 123, precision=1)
    '123.0 kB'
    >>> humanize_bytes(1024 * 12342, precision=1)
    '12.1 MB'
    >>> humanize_bytes(1024 * 12342, precision=2)
    '12.05 MB'
    >>> humanize_bytes(1024 * 1234, precision=2)
    '1.21 MB'
    >>> humanize_bytes(1024 * 1234 * 1111, precision=2)
    '1.31 GB'
    >>> humanize_bytes(1024 * 1234 * 1111, precision=1)
    '1.3 GB'

    """
    abbrevs = [
        (1 << 50, 'PB'),
        (1 << 40, 'TB'),
        (1 << 30, 'GB'),
        (1 << 20, 'MB'),
        (1 << 10, 'kB'),
        (1, 'B')
    ]

    if n == 1:
        return '1 B'

    for factor, suffix in abbrevs:
        if n >= factor:
            break

    # noinspection PyUnboundLocalVariable
    return f'{n / factor:.{precision}f} {suffix}'

3. yield

  • 参考: https://zhuanlan.zhihu.com/p/268605982

其实类似于程序的断电,比如程序运行到那里其实是返回一个生成器,然后当你下一步是才会执行,比较节省内存

from typing import List


def new(size: int = 1024 * 1024):
    yield new_data(size)


def new_data(size: int) -> List[int]:
    return [0] * size


data = new()
print(type(data))
print(len(next(data)))  # 只能执行一次 next不然报错
'''
<class 'generator'>
1048576
'''

脚本

base64输出

echo "aGVsbG8gcHl0aG9uCg==" | python -c "import sys,base64; print(sys.stdin.read())"

->

echo "aGVsbG8gcHl0aG9uCg==" | python -c "import sys,base64; print(base64.b64decode(sys.stdin.read()))"
-> stdout:
b'hello python\n'

文件操作

  • r ,w,x ,a四种类型(a: append, w=truncate+create, x=truncate+create if not exit)
  • b,t 文件类型

第一列可以和第二列文件类型组合,第一列不允许并存

import os


with open("file.log", "w") as file:
    for x in range(0, 100):
        file.write("hello world"+os.linesep)


with open("file.log","r") as file:
    for line in file.readlines():
        print(line)

json

import json

print(json.dumps({"k1": "v1", "k2": [1, 2, 3]}))
print(json.loads('{"k1": "v1", "k2": [1, 2, 3]}'))

如果是class,需要继承JSONEncoder和JSONDecoder实现子类 ,或者

import json, datetime

class Demo(object):
    def __init__(self, name: str, age: int, birthday: datetime.date):
        self.name = name
        self.agw = age
        self.birthday = birthday

    def to_json(self, _):
        return {"name": self.name, "age": self.agw, "birthday": self.birthday.strftime("%Y-%m-%d")}


data = Demo("tom", 18, datetime.date(2001, 1, 1))
print(json.dumps(data, default=data.to_json))

typing (申明类型)

官方文档: https://docs.python.org/zh-cn/3/library/typing.html

可以参考这篇文章: https://sikasjc.github.io/2018/07/14/type-hint-in-python/

对于喜欢静态类型的语言,我觉得是非常nice的

应上篇,续讲前文。今天咱来聊一下Dockerfile的使用 。


虽然可以通过docker commit命令来手动创建镜像,但是通过Dockerfile文件,可以帮助我们自动创建镜像,并且能够自定义创建过程。本质上,Dockerfile就是一系列命令和参数构成的脚本,这些命令应用于基础镜像并最终创建一个新的镜像,简化了从头到尾的构建流程并极大地简化了部署工作。

使用Dockerfile的优点:

  • 像编程一样构建镜像,支持分层构建及缓存。
  • 可以快速而精确的重新创建镜像以便于维护和升级。
  • 便于持续集成。
  • 可在任何地方快速构建镜像。


一、Dockerfile构建镜像步骤


1、创建Dockerfile文件,名字就是Dockerfile

2、docker build Dockerfile所在路径 -t 镜像名称[:tag]


二、Dockerfile指令


1、FORM

FORM指令是最重要的一个且必须为Dockerfile文件开篇的第一个非注释行,用于为映像文件构建过程指定基准镜像,后续的指令运行于此基准镜像所提供的运行环境。

基准镜像可以是任务可用镜像文件,默认情况下,docker build会在docker主机上查找指定的镜像文件,如果不存在,则会从Docker Hub Registry上拉取所需的镜像文件。

也就是说,任何新建镜像必须基于已有的镜像进行构建。


格式:FROM 镜像名称[:tag]

例如:FROM ngxin


2、MAINTAINER

用于让Dockerfile制作者提供本人的详细信息,此指令位置不限,但推荐放置FROM之后。

格式:MAINTAINER 作者信息

例如:MAINTAINER "lsy"


3、LABLE

为镜像指定标签,会继承基础镜像的LABLE,如果key相同,则覆盖。可替代MAINTANIER使用。


格式:LABLE key1=value1 key2=value2

例如:LABLE author=lsy

4、RUN

指定要运行并捕获到新容器镜像中的命令,包括安装文件、创建文件等,在容器创建过程中执行。


格式 :RUN 指令1 [&& 指令2]


注意:由于Dockerfile中每一个指令都会创建一层,所有层一起构成新的镜像。如果指令过多的话,会变得很臃肿,增加构建时间,所以可以将指令合并执行

例如:RUN mkdir -p /usr/lsy && echo 'this is lsy file' > /usr/lsy/lsy.html


例如下面这个Dockerfile文件:

基于nginx创建一个镜像,并创建/usr/lsy目录并创建lsy.html文件

FROM nginx
MAINTAINER "lsy"
RUN mkdir -p /usr/lsy &&  echo 'this is lsy file' > /usr/lsy/lsy.html

使用命令进行构建

docker build ./ -t my_nginx_1:v1.1

可以看到,docker会一层层的进行构建。

启动镜像:

docker run --rm --name my_nginx_1 -it my_nginx_1:v1.1 /bin/bash



可以看到,容器中确实是执行了RUN指令。


5、COPY

将宿主机的文件或者目录拷贝到容器的文件系统中,需相对于Dockerfile的路径。


格式:COPY <src> <dest>

文件复制准则:

  1. <src>必须是build上下文的相对路径。
  2. <src>是目录的话,则内部文件或子目录会递归复制,但是目录自身不会被复制
  3. 如果指定多个src,则dest必须是一个目录,且必须以/结尾
  4. 目标路径如果不存在,则会自动创建

例如:把Dockerfile同目录的test.html文件拷贝到容器中的/usr/lsy目录中

FROM nginx
MAINTAINER "lsy"
RUN mkdir -p /usr/lsy &&  echo 'this is lsy file' > /usr/lsy/lsy.html
COPY ./test.html /usr/lsy


使用docker build对Dockerfile进行构建:

启动容器查看文件是否已拷贝:


6、ADD

功能与COPY类似,还可以使用url规范从远程位置复制到容器中


格式 :ADD <source> <dest>

例如:ADD ./test.html /usr/lsy

ADD https://www.python.org/ftp/python/3.5.1/python-3.5.1.exe /temp/python-3.5.1.exe


7、WORKDIR

用于为其他Dockerfile指令(如 RUN、CMD)设置一个工作目录,并且还设置用于运行容器映像实例的工作目录。WORKDIR之后的指令都会基于设定的工作目录中运行。


格式:WORKDIR 路径

例如:将/usr/lsy设置为工作目录,然后在目录中创建一个a.html文件

FROM nginx
MAINTAINER "lsy"
RUN mkdir -p /usr/lsy
WORKDIR /usr/lsy
RUN touch a.html

使用docker build创建镜像

运行容器查看:

可以看到,进来容器就是在工作目录中,并且目录中有了需要创建的文件。


8、CMD

类似于RUN指令,CMD指令也可用于运行任何命令或应用程序,不过,两者的运行时间不同。

RUN指令运行于 镜像创建过程中,而CMD指令运行于基于Dockerfile构建出的镜像启动一个容器时。

CMD指令的目的在于为启动的容器指定默认要运行的程序,且其运行结束后,容器也将终止,不过CMD指令可以被docker run的命令行参数所覆盖。

Dockerfile中可以指定多个CMD命令,但只有最后一个才会生效。


格式:CMD <command>

CMD ['<executable>','<param1>','<param2>']

CMD ['<param1>','<param2>']

前两种语法跟RUN一样

第三种是用于为ENTERPOINT指令提供默认参数。


例如:CMD c:\Apache24\bin\httpd.exe -w

CMD ['/bin/bash','-c','c:\Apache24\bin\httpd.exe','-w']


9、ENTERPOINT

配置容器启动后执行的命令,并且不可被 docker run 提供的参数覆盖。每个 Dockerfile 中只能有一个ENTRYPOINT,当指定多个时,只有最后一个起效。如果有CMD,则CMD的命令被当作参数传递给ENTERPOINT。

不过,docker run命令的--entrypoint选项的参数可以对Dockerfile中的ENTRYPOINT进行覆盖。

Dockerfile中可存在多个 ENTRYPOINT指令,但只有最后一个 才会执行。


格式:ENTRYPOINT <command>

ENTRYPOINT ['<executable>','<param1>','<param2>']


10、ENV

用于为镜像定义所需的环境变量,并可被Dockerfile文件中位于其后的其他指令所调用。

调用格式为${variable_name}或$variable_name


格式:ENV key1=value1 key2=value2

ENV key value


11、ARG

构建参数,作用于ENV相同,不同的是ARG的参数只在构建镜像的时候起作用,也就是docker build的时候。


格式:ARG k=v


12、EXPOSE

用来指定端口,是容器内的应用可以通过端口与外界交互

作用跟docker run 命令中的 -p 一样


格式:EXPOSE 端口

例如:EXPOSE 80


13、VOLUME

用于在镜像中创建一个挂载点目录,以挂载Docker Host上的卷或其他容器上的卷

如果挂载点目录路径下此前的文件存在,docker run命令会在卷挂载完之后将此前的所有文件 复制到新挂载的卷中。


格式:VOLUME <路径>

VOLUME ["<路径1>", "<路径2>"...]


14、USER

用于执行后续命令的用户和用户组


格式 :USER 用户名[:用户组]

例如:USER root:root


15、HEALTHCHECK

用于指定某个程序或者指令来监控 docker 容器服务的运行状态。


格式:HEALTHCHECK [OPTIONS] CMD command

HEALTHCHECK NONE

第一个的功能是在容器内部运行一个命令来检查容器的健康状况

第二个的功能是在基础镜像中取消健康检查命令


[OPTIONS]的选项支持以下三中选项:

--interval=DURATION 两次检查默认的时间间隔为30秒

--timeout=DURATION 健康检查命令运行超时时长,默认30秒

--retries=N 当连续失败指定次数后,则容器被认为是不健康的,状态为unhealthy,默认次数是3

--start-period=DURATION 容器启动后多长时间开始执行,默认是0s


注意:

HEALTHCHECK命令只能出现一次,如果出现了多次,只有最后一个生效。


CMD后边的命令的返回值决定了本次健康检查是否成功,具体的返回值如下:

0: success - 表示容器是健康的

1: unhealthy - 表示容器已经不能工作了

2: reserved - 保留值


例如:定时 30s PING一下百度,如果PING失败,则返回1

FROM nginx
MAINTAINER "lsy"
HEALTHCHECK --timeout=3s \
        CMD curl -f http://localhost/ || exit 1

使用docker build构建镜像

运行容器,查看日志输出:


16、ONBUILD

用于延迟构建命令的执行。简单的说,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜像的过程中不会执行(假设镜像为 test-build)。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这是执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令。


格式 :ONBUILD <其它指令>

VOLUME

17、STOPSIGNAL

当容器退出时给系统发送什么样的指令


格式:STOPSIGNAL 指令


===============================

我是Liusy,一个喜欢健身的程序员。

获取更多干货以及最新消息,请关注公众号:上古伪神

如果对您有帮助,点个关注就是对我最大的支持!!!

使用Python进行Web开发,你需要掌握一系列关键的知识和技能。以下是一份涵盖基本和进阶方面的学习清单:

基础知识:

1、Python基础:

对Python语言的基本语法、数据类型、控制流程等有清晰的理解。

2、HTML和CSS:

掌握HTML(超文本标记语言)和CSS(层叠样式表),用于创建和美化网页。

3、JavaScript:

了解JavaScript,它是用于在网页上添加交互性和动态特效的脚本语言。

4、Web协议和网络基础:

了解HTTP/HTTPS协议,以及网络通信的基本原理。

5、前端框架:

学习至少一个前端框架,如React、Vue.js或Angular,用于构建动态、响应式的用户界面。

后端知识:

1、Web框架:

掌握Python的Web框架,例如Django、Flask或FastAPI。这些框架提供了一系列工具和模块,加速Web应用的开发。

2、模板引擎:

了解并使用模板引擎(如Jinja2),用于在服务器端生成动态的HTML页面。

3、数据库:

学习使用数据库,理解SQL语言,以及如何在Web应用中进行数据库操作。常见的数据库包括MySQL、PostgreSQL、SQLite等。

4、ORM(对象关系映射):

了解并使用ORM框架(例如Django的ORM或SQLAlchemy),简化与数据库的交互。

5、RESTful API设计:

学习设计和实现RESTful API,使你的应用可以通过API与其他系统进行通信。

安全性和性能优化:

1、安全性:

了解Web应用的常见安全问题,学习如何防范跨站脚本攻击(XSS)、跨站请求伪造(CSRF)等攻击。

2、身份验证和授权:

学习如何实现用户身份验证和授权机制,确保应用的安全性。

3、性能优化:

了解如何优化数据库查询、前端资源加载,以及使用缓存和CDN等技术提升应用性能。

版本控制和协作:

1、Git:

学习使用Git进行版本控制,以便有效地协作和管理代码。

2、团队协作:

了解团队协作工具,如GitHub、GitLab等,以便与其他开发者协同工作。

部署和运维:

1、服务器和部署:

了解Web服务器的基本原理,学习如何在服务器上部署Python应用。熟悉常见的部署工具,如Docker、Nginx等。

2、日志和监控:

学习记录和监控应用的技术,以便及时发现和解决问题。

3、自动化:

掌握自动化部署和测试的工具,如Jenkins、Travis CI等。

测试:

1、单元测试和集成测试:

学习编写和运行单元测试和集成测试,确保代码的质量和稳定性。

2、前端测试:

了解前端测试框架,如Jest、Testing Library等,用于测试前端组件和交互。

以上清单涵盖了Python Web开发的基本要素,你可以根据具体项目需求和兴趣深入学习相关的技术。实际项目和不断的实践也是巩固这些知识的重要途径。