5 proyectos de Python para principiantes con código fuente

Los 5 mejores proyectos de Python para principiantes con código fuente. Este tutorial proporcionará 5 ejemplos de código simples que son perfectos para los principiantes de Python. Cree un juego de adivinanzas de números en Python. Cree un generador de contraseñas simple en Python. Cree un verificador de contraseñas en Python. Cree un Web Scraper en Python. Cree un convertidor de divisas en Python

Ejemplos de programas de Python: ejemplos de código simple para principiantes

Mark Twain dijo que el secreto para salir adelante es empezar. La programación puede parecer abrumadora para los principiantes, pero la mejor manera de comenzar es sumergirse y comenzar a escribir código.

Los ejemplos de código simples son una excelente manera para que los principiantes se mojen los pies y aprendan los conceptos básicos de la programación. En este artículo, proporcionaré una serie de ejemplos de código simples que son perfectos para los principiantes de Python.

Estos ejemplos cubren una variedad de conceptos de programación y lo ayudarán a desarrollar una base sólida en la programación. Ya sea que sea nuevo en la programación o simplemente esté buscando refrescar sus habilidades, estos ejemplos de código lo ayudarán a comenzar su viaje de codificación.

Si necesita aprender algunos conceptos básicos de Python, he agregado algunos recursos útiles al final de este tutorial.

Tabla de contenido:

  1. Cómo construir un juego de adivinanzas de números en Python
  2. Cómo construir un generador de contraseñas simple en Python
  3. Cómo construir un verificador de contraseñas en Python
  4. Cómo construir un Web Scraper en Python
  5. Cómo construir un convertidor de divisas en Python

Cómo construir un juego de adivinanzas de números en Python

En este proyecto, creará un juego simple de adivinanzas que le permite al usuario adivinar un número aleatorio entre 1 y 100. El programa le dará pistas al usuario después de cada intento, indicando si su intento fue demasiado alto o demasiado bajo, hasta que el usuario adivina el número correcto.

Código :

import random

secret_number = random.randint(1, 100)

while True:
    guess = int(input("Guess the number between 1 and 100: "))
    
    if guess == secret_number:
        print("Congratulations! You guessed the number!")
        break
    elif guess < secret_number:
        print("Too low! Try again.")
    else:
        print("Too high! Try again.")

Explicación :

  • Comience por importar el randommódulo, que le permitirá generar un número aleatorio.
  • Genere un número aleatorio entre 1 y 100 utilizando la randint()función del randommódulo y asígnelo a una variable.
  • Cree un bucle que permita al usuario adivinar el número hasta que acierte. Dentro del ciclo, solicite al usuario que ingrese su suposición usando la input()función y convierta su entrada a un número entero usando la int()función.
  • Agregue una declaración condicional dentro del bucle que verifique si la suposición del usuario es correcta, demasiado alta o demasiado baja. Si la suposición es correcta, imprima un mensaje de felicitación y salga del bucle. Si la suposición es demasiado alta o demasiado baja, imprima un mensaje de sugerencia para ayudar al usuario a adivinar el número correctamente.
  • ¡Ejecuta el programa y juega el juego de adivinanzas!

Cómo construir un generador de contraseñas simple en Python

Un generador de contraseñas, como su nombre lo indica, genera una contraseña aleatoria de una longitud particular utilizando diferentes combinaciones de caracteres y caracteres especiales.

Código :

import random
import string

def generate_password(length):
    """This function generates a random password
    of a given length using a combination of
    uppercase letters, lowercase letters,
    digits, and special characters"""
    
    # Define a string containing all possible characters
    all_chars = string.ascii_letters + string.digits + string.punctuation
    
    # Generate a password using a random selection of characters
    password = "".join(random.choice(all_chars) for i in range(length))
    
    return password

# Test the function by generating a password of length 10
password = generate_password(10)
print(password)

Explicación :

  • Importamos los módulos randomy stringque usamos para generar valores aleatorios y trabajar con cadenas, respectivamente.
  • A continuación, definimos una función llamada generate_passwordque toma un solo parámetro length, que especifica la longitud de la contraseña que debe generarse.
  • Dentro de la función, definimos una cadena llamada all_charsque contiene todos los caracteres posibles que se pueden usar para generar la contraseña. Usamos las constantes string.ascii_letters, string.digitsy string.punctuationpara crear esta cadena.
  • Luego usamos la comprensión de listas para generar una lista de lengthcaracteres aleatorios de la all_charscadena usando la random.choice()función. Finalmente, unimos estos caracteres en una sola cadena usando la "".join()función y devolvemos el resultado.
  • Para probar la función, la llamamos con un argumento de 10 para generar una contraseña de longitud 10 e imprimir el resultado.

Tenga en cuenta que este es un generador de contraseñas muy simple y puede no ser adecuado para su uso en escenarios del mundo real donde la seguridad es una preocupación.

Cómo construir un verificador de contraseñas en Python

Construiremos un verificador de contraseñas en esta sección. Su trabajo es verificar si una contraseña es lo suficientemente segura en función de algunos de los criterios que establecemos. Imprimirá un error si no se cumple alguno de los criterios de la contraseña.

Código :

# Define a function to check if the password is strong enough
def password_checker(password):
    # Define the criteria for a strong password
    min_length = 8
    has_uppercase = False
    has_lowercase = False
    has_digit = False
    has_special_char = False
    special_chars = "!@#$%^&*()-_=+[{]}\|;:',<.>/?"
    
    # Check the length of the password
    if len(password) < min_length:
        print("Password is too short!")
        return False
    
    # Check if the password contains an uppercase letter, lowercase letter, digit, and special character
    for char in password:
        if char.isupper():
            has_uppercase = True
        elif char.islower():
            has_lowercase = True
        elif char.isdigit():
            has_digit = True
        elif char in special_chars:
            has_special_char = True
    
    # Print an error message for each missing criteria
    if not has_uppercase:
        print("Password must contain at least one uppercase letter!")
        return False
    if not has_lowercase:
        print("Password must contain at least one lowercase letter!")
        return False
    if not has_digit:
        print("Password must contain at least one digit!")
        return False
    if not has_special_char:
        print("Password must contain at least one special character!")
        return False
    
    # If all criteria are met, print a success message
    print("Password is strong!")
    return True

# Prompt the user to enter a password and check if it meets the criteria
password = input("Enter a password: ")
password_checker(password)

Explicación :

  • En este código, definimos una función llamada password_checker()que toma una contraseña como argumento y verifica si cumple con ciertos criterios de seguridad.
  • Primero definimos los criterios para una contraseña segura: una longitud mínima de 8 caracteres, al menos una letra mayúscula, una letra minúscula, un dígito y un carácter especial.
  • Luego verificamos la longitud de la contraseña y si contiene los tipos de caracteres requeridos usando un bucle for que itera a través de cada carácter de la contraseña.
  • Si la contraseña no cumple con alguno de los criterios, imprimimos un mensaje de error y regresamos Falsepara indicar que la contraseña no es lo suficientemente segura. De lo contrario, imprimimos un mensaje de éxito y regresamos True.
  • Finalmente, solicitamos al usuario que ingrese una contraseña usando la input()función y la pase a la password_checker()función para verificar si cumple con los criterios.

Cómo construir un Web Scraper en Python

Un raspador web raspa/obtiene datos de páginas web y los guarda en cualquier formato que queramos, ya sea .csv o .txt. Construiremos un web scraper simple en esta sección usando una biblioteca de Python llamada Beautiful Soup.

Código :

import requests
from bs4 import BeautifulSoup

# Set the URL of the webpage you want to scrape
url = 'https://www.example.com'

# Send an HTTP request to the URL and retrieve the HTML content
response = requests.get(url)

# Create a BeautifulSoup object that parses the HTML content
soup = BeautifulSoup(response.content, 'html.parser')

# Find all the links on the webpage
links = soup.find_all('a')

# Print the text and href attribute of each link
for link in links:
    print(link.get('href'), link.text)

Explicación :

  • En este código, primero importamos los módulos requestsy BeautifulSoupque se utilizan para realizar solicitudes HTTP y analizar contenido HTML, respectivamente.
  • A continuación, establecemos la URL de la página web que queremos raspar en una variable llamada url.
  • Luego usamos la requests.get()función para enviar una solicitud HTTP GET a la URL y recuperar el contenido HTML de la página web como respuesta.
  • Creamos un BeautifulSoupobjeto llamado soupque analiza el contenido HTML de la respuesta utilizando el html.parseranalizador.
  • Luego usamos el soup.find_all()método para encontrar todos los enlaces en la página web y almacenarlos en una variable llamada links.
  • Finalmente, usamos un ciclo for para iterar a través de cada enlace linkse imprimir el texto y el atributo href de cada enlace usando el link.get()método.

Cómo construir un convertidor de divisas en Python

Un convertidor de moneda es un programa que ayuda a los usuarios a convertir el valor de una moneda en otra moneda. Puede usarlo para una variedad de propósitos, como calcular el costo de compras internacionales, estimar gastos de viaje o analizar datos financieros.

Nota: utilizaremos ExchangeRate-API para obtener los datos del tipo de cambio, que es una API gratuita y de código abierto para los tipos de cambio de divisas. Pero hay otras API disponibles que pueden tener diferentes límites de uso o requisitos.

Código:

# Import the necessary modules
import requests

# Define a function to convert currencies
def currency_converter(amount, from_currency, to_currency):
    # Set the API endpoint for currency conversion
    api_endpoint = f"https://api.exchangerate-api.com/v4/latest/{from_currency}"
    
    # Send a GET request to the API endpoint
    response = requests.get(api_endpoint)
    
    # Get the JSON data from the response
    data = response.json()
    
    # Extract the exchange rate for the target currency
    exchange_rate = data["rates"][to_currency]
    
    # Calculate the converted amount
    converted_amount = amount * exchange_rate
    
    # Return the converted amount
    return converted_amount

# Prompt the user to enter the amount, source currency, and target currency
amount = float(input("Enter the amount: "))
from_currency = input("Enter the source currency code: ").upper()
to_currency = input("Enter the target currency code: ").upper()

# Convert the currency and print the result
result = currency_converter(amount, from_currency, to_currency)
print(f"{amount} {from_currency} is equal to {result} {to_currency}")

Explicación :

  • En este código, definimos una función llamada currency_converter()que toma una cantidad, un código de moneda de origen y un código de moneda de destino como argumentos y devuelve la cantidad convertida.
  • Primero configuramos el punto final de la API para la conversión de divisas usando el from_currencyparámetro y el requestsmódulo para enviar una solicitud GET al punto final.
  • A continuación, extraemos el tipo de cambio de la moneda de destino de los datos JSON devueltos por la API mediante el to_currencyparámetro y calculamos el importe convertido multiplicando el tipo de cambio por el amountparámetro.
  • Finalmente, solicitamos al usuario que ingrese el amount, from_currencyy to_currencyusando la input()función y los pase a la currency_converter()función para convertir la moneda. Luego, la cantidad convertida se imprime utilizando el formato de cadena.

Conclusión

Todos estos proyectos son muy simples y fáciles de construir. Si realmente desea mejorar sus habilidades con Python, le aconsejo que tome el código, lo modifique y lo edite, y lo desarrolle. Puede convertir muchos de estos proyectos simples en aplicaciones mucho más complejas si lo desea.

Si necesita aprender algunos conceptos básicos de Python, consulte estos útiles recursos:

  • Cómo construir tu primer proyecto de Python
  • Python para todos: curso universitario completo del Dr. Chuck

¡Feliz codificación!

Fuente: https://www.freecodecamp.org

#python

What is GEEK

Buddha Community

5 proyectos de Python para principiantes con código fuente
Shardul Bhatt

Shardul Bhatt

1626775355

Why use Python for Software Development

No programming language is pretty much as diverse as Python. It enables building cutting edge applications effortlessly. Developers are as yet investigating the full capability of end-to-end Python development services in various areas. 

By areas, we mean FinTech, HealthTech, InsureTech, Cybersecurity, and that's just the beginning. These are New Economy areas, and Python has the ability to serve every one of them. The vast majority of them require massive computational abilities. Python's code is dynamic and powerful - equipped for taking care of the heavy traffic and substantial algorithmic capacities. 

Programming advancement is multidimensional today. Endeavor programming requires an intelligent application with AI and ML capacities. Shopper based applications require information examination to convey a superior client experience. Netflix, Trello, and Amazon are genuine instances of such applications. Python assists with building them effortlessly. 

5 Reasons to Utilize Python for Programming Web Apps 

Python can do such numerous things that developers can't discover enough reasons to admire it. Python application development isn't restricted to web and enterprise applications. It is exceptionally adaptable and superb for a wide range of uses.

Robust frameworks 

Python is known for its tools and frameworks. There's a structure for everything. Django is helpful for building web applications, venture applications, logical applications, and mathematical processing. Flask is another web improvement framework with no conditions. 

Web2Py, CherryPy, and Falcon offer incredible capabilities to customize Python development services. A large portion of them are open-source frameworks that allow quick turn of events. 

Simple to read and compose 

Python has an improved sentence structure - one that is like the English language. New engineers for Python can undoubtedly understand where they stand in the development process. The simplicity of composing allows quick application building. 

The motivation behind building Python, as said by its maker Guido Van Rossum, was to empower even beginner engineers to comprehend the programming language. The simple coding likewise permits developers to roll out speedy improvements without getting confused by pointless subtleties. 

Utilized by the best 

Alright - Python isn't simply one more programming language. It should have something, which is the reason the business giants use it. Furthermore, that too for different purposes. Developers at Google use Python to assemble framework organization systems, parallel information pusher, code audit, testing and QA, and substantially more. Netflix utilizes Python web development services for its recommendation algorithm and media player. 

Massive community support 

Python has a steadily developing community that offers enormous help. From amateurs to specialists, there's everybody. There are a lot of instructional exercises, documentation, and guides accessible for Python web development solutions. 

Today, numerous universities start with Python, adding to the quantity of individuals in the community. Frequently, Python designers team up on various tasks and help each other with algorithmic, utilitarian, and application critical thinking. 

Progressive applications 

Python is the greatest supporter of data science, Machine Learning, and Artificial Intelligence at any enterprise software development company. Its utilization cases in cutting edge applications are the most compelling motivation for its prosperity. Python is the second most well known tool after R for data analytics.

The simplicity of getting sorted out, overseeing, and visualizing information through unique libraries makes it ideal for data based applications. TensorFlow for neural networks and OpenCV for computer vision are two of Python's most well known use cases for Machine learning applications.

Summary

Thinking about the advances in programming and innovation, Python is a YES for an assorted scope of utilizations. Game development, web application development services, GUI advancement, ML and AI improvement, Enterprise and customer applications - every one of them uses Python to its full potential. 

The disadvantages of Python web improvement arrangements are regularly disregarded by developers and organizations because of the advantages it gives. They focus on quality over speed and performance over blunders. That is the reason it's a good idea to utilize Python for building the applications of the future.

#python development services #python development company #python app development #python development #python in web development #python software development

Wayne  Richards

Wayne Richards

1660525440

Algunas Mejores Prácticas De Docker Para Desarrolladores De Python

Este artículo analiza algunas de las mejores prácticas a seguir al escribir Dockerfiles y trabajar con Docker en general. Si bien la mayoría de las prácticas enumeradas se aplican a todos los desarrolladores, independientemente del idioma, algunas se aplican solo a aquellos que desarrollan aplicaciones basadas en Python.

Dockerfiles

Usar compilaciones de varias etapas

Aproveche las compilaciones de varias etapas para crear imágenes de Docker más eficientes y seguras.

Las compilaciones de Docker de varias etapas le permiten dividir sus Dockerfiles en varias etapas. Por ejemplo, puede tener una etapa para compilar y crear su aplicación, que luego puede copiarse en etapas posteriores. Dado que solo se usa la etapa final para crear la imagen, las dependencias y herramientas asociadas con la creación de su aplicación se descartan, lo que deja una imagen esbelta y modular lista para la producción.

Ejemplo de desarrollo web:

# temp stage
FROM python:3.9-slim as builder

WORKDIR /app

ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

RUN apt-get update && \
    apt-get install -y --no-install-recommends gcc

COPY requirements.txt .
RUN pip wheel --no-cache-dir --no-deps --wheel-dir /app/wheels -r requirements.txt


# final stage
FROM python:3.9-slim

WORKDIR /app

COPY --from=builder /app/wheels /wheels
COPY --from=builder /app/requirements.txt .

RUN pip install --no-cache /wheels/*

En este ejemplo, se requiere el compilador GCC para instalar ciertos paquetes de Python, por lo que agregamos una etapa temporal de tiempo de compilación para manejar la fase de compilación. Dado que la imagen final en tiempo de ejecución no contiene GCC, es mucho más ligera y segura.

Comparación de tamaño:

REPOSITORY                 TAG                    IMAGE ID       CREATED          SIZE
docker-single              latest                 8d6b6a4d7fb6   16 seconds ago   259MB
docker-multi               latest                 813c2fa9b114   3 minutes ago    156MB

Ejemplo de ciencia de datos:

# temp stage
FROM python:3.9 as builder

RUN pip wheel --no-cache-dir --no-deps --wheel-dir /wheels jupyter pandas


# final stage
FROM python:3.9-slim

WORKDIR /notebooks

COPY --from=builder /wheels /wheels
RUN pip install --no-cache /wheels/*

Comparación de tamaño:

REPOSITORY                  TAG                   IMAGE ID       CREATED         SIZE
ds-multi                    latest                b4195deac742   2 minutes ago   357MB
ds-single                   latest                7c23c43aeda6   6 minutes ago   969MB

En resumen, las compilaciones de varias etapas pueden reducir el tamaño de las imágenes de producción, lo que le ayuda a ahorrar tiempo y dinero. Además, esto simplificará sus contenedores de producción. Además, debido al tamaño más pequeño y la simplicidad, existe potencialmente una superficie de ataque más pequeña.

Ordene los comandos de Dockerfile de forma adecuada

Preste mucha atención al orden de los comandos de Dockerfile para aprovechar el almacenamiento en caché de capas.

Docker almacena en caché cada paso (o capa) en un Dockerfile particular para acelerar las compilaciones posteriores. Cuando un paso cambia, la memoria caché se invalidará no solo para ese paso en particular, sino también para todos los pasos posteriores.

Ejemplo:

FROM python:3.9-slim

WORKDIR /app

COPY sample.py .

COPY requirements.txt .

RUN pip install -r /requirements.txt

In this Dockerfile, we copied over the application code before installing the requirements. Now, each time we change sample.py, the build will reinstall the packages. This is very inefficient, especially when using a Docker container as a development environment. Therefore, it's crucial to keep the files that frequently change towards the end of the Dockerfile.

You can also help prevent unwanted cache invalidations by using a .dockerignore file to exclude unnecessary files from being added to the Docker build context and the final image. More on this here shortly.

So, in the above Dockerfile, you should move the COPY sample.py . command to the bottom:

FROM python:3.9-slim

WORKDIR /app

COPY requirements.txt .

RUN pip install -r /requirements.txt

COPY sample.py .

Notes:

  1. Always put layers that are likely to change as low as possible in the Dockerfile.
  2. Combine RUN apt-get update and RUN apt-get install commands. (This also helps to reduce the image size. We'll touch on this shortly.)
  3. If you want to turn off caching for a particular Docker build, add the --no-cache=True flag.

Use Small Docker Base Images

Smaller Docker images are more modular and secure.

Building, pushing, and pulling images is quicker with smaller images. They also tend to be more secure since they only include the necessary libraries and system dependencies required for running your application.

Which Docker base image should you use?

Unfortunately, it depends.

Here's a size comparison of various Docker base images for Python:

REPOSITORY   TAG                 IMAGE ID       CREATED      SIZE
python       3.9.6-alpine3.14    f773016f760e   3 days ago   45.1MB
python       3.9.6-slim          907fc13ca8e7   3 days ago   115MB
python       3.9.6-slim-buster   907fc13ca8e7   3 days ago   115MB
python       3.9.6               cba42c28d9b8   3 days ago   886MB
python       3.9.6-buster        cba42c28d9b8   3 days ago   886MB

While the Alpine flavor, based on Alpine Linux, is the smallest, it can often lead to increased build times if you can't find compiled binaries that work with it. As a result, you may end up having to build the binaries yourself, which can increase the image size (depending on the required system-level dependencies) and the build times (due to having to compile from the source).

Refer to The best Docker base image for your Python application and Using Alpine can make Python Docker builds 50× slower for more on why it's best to avoid using Alpine-based base images.

In the end, it's all about balance. When in doubt, start with a *-slim flavor, especially in development mode, as you're building your application. You want to avoid having to continually update the Dockerfile to install necessary system-level dependencies when you add a new Python package. As you harden your application and Dockerfile(s) for production, you may want to explore using Alpine for the final image from a multi-stage build.

Also, don't forget to update your base images regularly to improve security and boost performance. When a new version of a base image is released -- i.e., 3.9.6-slim -> 3.9.7-slim -- you should pull the new image and update your running containers to get all the latest security patches.

Minimize the Number of Layers

Es una buena idea combinar los comandos RUN, COPYy ADDtanto como sea posible ya que crean capas. Cada capa aumenta el tamaño de la imagen ya que se almacenan en caché. Por lo tanto, a medida que aumenta el número de capas, también aumenta el tamaño.

Puedes probar esto con el docker historycomando:

$ docker images
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
dockerfile   latest    180f98132d02   51 seconds ago   259MB

$ docker history 180f98132d02

IMAGE          CREATED              CREATED BY                                      SIZE      COMMENT
180f98132d02   58 seconds ago       COPY . . # buildkit                             6.71kB    buildkit.dockerfile.v0
<missing>      58 seconds ago       RUN /bin/sh -c pip install -r requirements.t…   35.5MB    buildkit.dockerfile.v0
<missing>      About a minute ago   COPY requirements.txt . # buildkit              58B       buildkit.dockerfile.v0
<missing>      About a minute ago   WORKDIR /app
...

Toma nota de los tamaños. Solo los comandos , y agregan tamaño a la RUNimagen COPY. ADDPuede reducir el tamaño de la imagen combinando comandos siempre que sea posible. Por ejemplo:

RUN apt-get update
RUN apt-get install -y netcat

Se pueden combinar en un solo RUNcomando:

RUN apt-get update && apt-get install -y netcat

Por lo tanto, se crea una sola capa en lugar de dos, lo que reduce el tamaño de la imagen final.

Si bien es una buena idea reducir la cantidad de capas, es mucho más importante que sea menos un objetivo en sí mismo y más un efecto secundario de reducir el tamaño de la imagen y los tiempos de construcción. En otras palabras, concéntrese más en las tres prácticas anteriores (compilaciones de varias etapas, orden de los comandos de Dockerfile y uso de una imagen base pequeña) que en tratar de optimizar cada comando.

Notas:

  1. RUN, COPYy ADDcada uno crea capas.
  2. Cada capa contiene las diferencias con respecto a la capa anterior.
  3. Las capas aumentan el tamaño de la imagen final.

Puntas:

  1. Combinar comandos relacionados.
  2. Elimine los archivos innecesarios en el mismo EJECUTAR stepque los creó.
  3. Minimice la cantidad de veces apt-get upgradeque se ejecuta, ya que actualiza todos los paquetes a la última versión.
  4. Con compilaciones de varias etapas, no se preocupe demasiado por optimizar demasiado los comandos en las etapas temporales.

Finalmente, para facilitar la lectura, es una buena idea ordenar los argumentos de varias líneas alfanuméricamente:

RUN apt-get update && apt-get install -y \
    git \
    gcc \
    matplotlib \
    pillow  \
    && rm -rf /var/lib/apt/lists/*

Usar contenedores sin privilegios

De forma predeterminada, Docker ejecuta procesos de contenedores como root dentro de un contenedor. Sin embargo, esta es una mala práctica ya que un proceso que se ejecuta como root dentro del contenedor se ejecuta como root en el host de Docker. Por lo tanto, si un atacante obtiene acceso a su contenedor, tiene acceso a todos los privilegios de root y puede realizar varios ataques contra el host de Docker, como:

  1. copiar información confidencial del sistema de archivos del host al contenedor
  2. ejecutando comandos remotos

Para evitar esto, asegúrese de ejecutar los procesos del contenedor con un usuario que no sea root:

RUN addgroup --system app && adduser --system --group app

USER app

Puede ir un paso más allá y eliminar el acceso de shell y asegurarse de que tampoco haya un directorio de inicio:

RUN addgroup --gid 1001 --system app && \
    adduser --no-create-home --shell /bin/false --disabled-password --uid 1001 --system --group app

USER app

Verify:

$ docker run -i sample id

uid=1001(app) gid=1001(app) groups=1001(app)

Here, the application within the container runs under a non-root user. However, keep in mind, the Docker daemon and the container itself is still running with root privileges. Be sure to review Run the Docker daemon as a non-root user for help with running both the daemon and containers as a non-root user.

Prefer COPY Over ADD

Use COPY unless you're sure you need the additional functionality that comes with ADD.

What's the difference between COPY and ADD?

Both commands allow you to copy files from a specific location into a Docker image:

ADD <src> <dest>
COPY <src> <dest>

While they look like they serve the same purpose, ADD has some additional functionality:

  • COPY is used for copying local files or directories from the Docker host to the image.
  • ADD can be used for the same thing as well as downloading external files. Also, if you use a compressed file (tar, gzip, bzip2, etc.) as the <src> parameter, ADD will automatically unpack the contents to the given location.
# copy local files on the host  to the destination
COPY /source/path  /destination/path
ADD /source/path  /destination/path

# download external file and copy to the destination
ADD http://external.file/url  /destination/path

# copy and extract local compresses files
ADD source.file.tar.gz /destination/path

Cache Python Packages to the Docker Host

When a requirements file is changed, the image needs to be rebuilt to install the new packages. The earlier steps will be cached, as mentioned in Minimize the Number of Layers. Downloading all packages while rebuilding the image can cause a lot of network activity and takes a lot of time. Each rebuild takes up the same amount of time for downloading common packages across builds.

You can avoid this by mapping the pip cache directory to a directory on the host machine. So for each rebuild, the cached versions persist and can improve the build speed.

Add a volume to the docker run as -v $HOME/.cache/pip-docker/:/root/.cache/pip or as a mapping in the Docker Compose file.

The directory presented above is only for reference. Make sure you map the cache directory and not the site-packages (where the built packages reside).

Moving the cache from the docker image to the host can save you space in the final image.

If you're leveraging Docker BuildKit, use BuildKit cache mounts to manage the cache:

# syntax = docker/dockerfile:1.2

...

COPY requirements.txt .

RUN --mount=type=cache,target=/root/.cache/pip \
        pip install -r requirements.txt

...

Run Only One Process Per Container

Why is it recommended to run only one process per container?

Let's assume your application stack consists of a two web servers and a database. While you could easily run all three from a single container, you should run each in a separate container to make it easier to reuse and scale each of the individual services.

  1. Scaling - With each service in a separate container, you can scale one of your web servers horizontally as needed to handle more traffic.
  2. Reusability - Perhaps you have another service that needs a containerized database. You can simply reuse the same database container without bringing two unnecessary services along with it.
  3. Logging - Coupling containers makes logging much more complex. We'll address this in further detail later in this article.
  4. Portability and Predictability - It's much easier to make security patches or debug an issue when there's less surface area to work with.

Prefer Array Over String Syntax

You can write the CMD and ENTRYPOINT commands in your Dockerfiles in both array (exec) or string (shell) formats:

# array (exec)
CMD ["gunicorn", "-w", "4", "-k", "uvicorn.workers.UvicornWorker", "main:app"]

# string (shell)
CMD "gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app"

Both are correct and achieve nearly the same thing; however, you should use the exec format whenever possible. From the Docker documentation:

  1. Make sure you're using the exec form of CMD and ENTRYPOINT in your Dockerfile.
  2. Por ejemplo, ["program", "arg1", "arg2"]no use "program arg1 arg2". El uso de la forma de cadena hace que Docker ejecute su proceso usando bash, que no maneja las señales correctamente. Compose siempre usa el formulario JSON, así que no se preocupe si anula el comando o el punto de entrada en su archivo de Compose.

Entonces, dado que la mayoría de los shells no procesan señales para procesos secundarios, si usa el formato de shell, CTRL-C(que genera un SIGTERM) puede que no detenga un proceso secundario.

Ejemplo:

FROM ubuntu:18.04

# BAD: shell format
ENTRYPOINT top -d

# GOOD: exec format
ENTRYPOINT ["top", "-d"]

Prueba ambos. Tenga en cuenta que con el sabor del formato de shell, CTRL-Cno matará el proceso. En su lugar, verás ^C^C^C^C^C^C^C^C^C^C^C.

Otra advertencia es que el formato de shell lleva el PID del shell, no el proceso en sí.

# array format
root@18d8fd3fd4d2:/app# ps ax
  PID TTY      STAT   TIME COMMAND
    1 ?        Ss     0:00 python manage.py runserver 0.0.0.0:8000
    7 ?        Sl     0:02 /usr/local/bin/python manage.py runserver 0.0.0.0:8000
   25 pts/0    Ss     0:00 bash
  356 pts/0    R+     0:00 ps ax


# string format
root@ede24a5ef536:/app# ps ax
  PID TTY      STAT   TIME COMMAND
    1 ?        Ss     0:00 /bin/sh -c python manage.py runserver 0.0.0.0:8000
    8 ?        S      0:00 python manage.py runserver 0.0.0.0:8000
    9 ?        Sl     0:01 /usr/local/bin/python manage.py runserver 0.0.0.0:8000
   13 pts/0    Ss     0:00 bash
  342 pts/0    R+     0:00 ps ax

Comprender la diferencia entre ENTRYPOINT y CMD

¿Debo usar ENTRYPOINT o CMD para ejecutar procesos de contenedor?

Hay dos formas de ejecutar comandos en un contenedor:

CMD ["gunicorn", "config.wsgi", "-b", "0.0.0.0:8000"]

# and

ENTRYPOINT ["gunicorn", "config.wsgi", "-b", "0.0.0.0:8000"]

Ambos esencialmente hacen lo mismo: inicie la aplicación config.wsgicon un servidor Gunicorn y vincúlela a 0.0.0.0:8000.

El CMDse anula fácilmente. Si ejecuta docker run <image_name> uvicorn config.asgi, el CMD anterior se reemplaza por los nuevos argumentos, por ejemplo, uvicorn config.asgi. Mientras que para anular el ENTRYPOINTcomando, se debe especificar la --entrypointopción:

docker run --entrypoint uvicorn config.asgi <image_name>

Aquí, está claro que estamos anulando el punto de entrada. Por lo tanto, se recomienda usar ENTRYPOINTover CMDpara evitar anular accidentalmente el comando.

Se pueden usar juntos también.

Por ejemplo:

ENTRYPOINT ["gunicorn", "config.wsgi", "-w"]
CMD ["4"]

Cuando se usan juntos de esta manera, el comando que se ejecuta para iniciar el contenedor es:

gunicorn config.wsgi -w 4

Como se discutió anteriormente, CMDse anula fácilmente. Por lo tanto, CMDpuede usarse para pasar argumentos al ENTRYPOINTcomando. El número de trabajadores se puede cambiar fácilmente así:

docker run <image_name> 6

Esto iniciará el contenedor con seis trabajadores de Gunicorn en lugar de cuatro.

Incluir una instrucción HEALTHCHECK

Use a HEALTHCHECKpara determinar si el proceso que se ejecuta en el contenedor no solo está en funcionamiento, sino que también está "en buen estado".

Docker expone una API para verificar el estado del proceso que se ejecuta en el contenedor, lo que proporciona mucha más información que solo si el proceso se está "ejecutando" o no, ya que "ejecutando" cubre "está en funcionamiento", "todavía se está iniciando", e incluso "atrapado en algún estado de error de bucle infinito". Puede interactuar con esta API a través de la instrucción HEALTHCHECK .

Por ejemplo, si está entregando una aplicación web, puede usar lo siguiente para determinar si el /punto final está activo y puede manejar las solicitudes de entrega:

HEALTHCHECK CMD curl --fail http://localhost:8000 || exit 1

Si ejecuta docker ps, puede ver el estado del archivo HEALTHCHECK.

Ejemplo saludable:

CONTAINER ID   IMAGE         COMMAND                  CREATED          STATUS                            PORTS                                       NAMES
09c2eb4970d4   healthcheck   "python manage.py ru…"   10 seconds ago   Up 8 seconds (health: starting)   0.0.0.0:8000->8000/tcp, :::8000->8000/tcp   xenodochial_clarke

Ejemplo poco saludable:

CONTAINER ID   IMAGE         COMMAND                  CREATED              STATUS                          PORTS                                       NAMES
09c2eb4970d4   healthcheck   "python manage.py ru…"   About a minute ago   Up About a minute (unhealthy)   0.0.0.0:8000->8000/tcp, :::8000->8000/tcp   xenodochial_clarke

Puede ir un paso más allá y configurar un punto de conexión personalizado que se use solo para las comprobaciones de estado y luego configurarlo HEALTHCHECKpara realizar pruebas con los datos devueltos. Por ejemplo, si el extremo devuelve una respuesta JSON de {"ping": "pong"}, puede indicarle HEALTHCHECKque valide el cuerpo de la respuesta.

Así es como se ve el estado de la verificación de estado usando docker inspect:

❯ docker inspect --format "{{json .State.Health }}" ab94f2ac7889
{
  "Status": "healthy",
  "FailingStreak": 0,
  "Log": [
    {
      "Start": "2021-09-28T15:22:57.5764644Z",
      "End": "2021-09-28T15:22:57.7825527Z",
      "ExitCode": 0,
      "Output": "..."

Aquí, la salida se recorta, ya que contiene la salida HTML completa.

También puede agregar una verificación de estado a un archivo de Docker Compose:

version: "3.8"

services:
  web:
    build: .
    ports:
      - '8000:8000'
    healthcheck:
      test: curl --fail http://localhost:8000 || exit 1
      interval: 10s
      timeout: 10s
      start_period: 10s
      retries: 3

Opciones:

  • test: El comando para probar.
  • interval: El intervalo para probar, es decir, probar cada xunidad de tiempo.
  • timeout: Tiempo máximo de espera de la respuesta.
  • start_period: Cuándo iniciar la comprobación de estado. Se puede usar cuando se realizan tareas adicionales antes de que los contenedores estén listos, como ejecutar migraciones.
  • retries: Máximo de reintentos antes de designar una prueba como failed.

Si está utilizando una herramienta de orquestación que no sea Docker Swarm, es decir, Kubernetes o AWS ECS, es muy probable que la herramienta tenga su propio sistema interno para manejar las comprobaciones de estado. Consulte los documentos de la herramienta en particular antes de agregar la HEALTHCHECKinstrucción.

Imágenes

Versión Docker Imágenes

Siempre que sea posible, evite usar la latestetiqueta.

Si confía en la latestetiqueta (que no es realmente una "etiqueta" ya que se aplica de manera predeterminada cuando una imagen no está etiquetada explícitamente), no puede saber qué versión de su código se está ejecutando en función de la etiqueta de la imagen. Hace que sea un desafío hacer reversiones y facilita sobrescribirlo (ya sea accidental o maliciosamente). Las etiquetas, como su infraestructura e implementaciones, deben ser inmutables .

Independientemente de cómo trate sus imágenes internas, nunca debe usar la latestetiqueta para las imágenes base, ya que podría implementar sin darse cuenta una nueva versión con cambios importantes en la producción.

Para las imágenes internas, use etiquetas descriptivas para que sea más fácil saber qué versión del código se está ejecutando, manejar las reversiones y evitar colisiones de nombres.

Por ejemplo, puede utilizar los siguientes descriptores para crear una etiqueta:

  1. Marcas de tiempo
  2. ID de imagen de Docker
  3. Hashes de confirmación de Git
  4. Versión semántica

Para obtener más opciones, consulte esta respuesta de la pregunta de desbordamiento de pila "Versionar correctamente las imágenes de Docker".

Por ejemplo:

docker build -t web-prod-a072c4e5d94b5a769225f621f08af3d4bf820a07-0.1.4 .

Aquí, usamos lo siguiente para formar la etiqueta:

  1. Nombre del proyecto:web
  2. Nombre del entorno:prod
  3. Hash de confirmación de Git:a072c4e5d94b5a769225f621f08af3d4bf820a07
  4. Versión semántica:0.1.4

Es esencial elegir un esquema de etiquetado y ser coherente con él. Dado que los hashes de confirmación facilitan la vinculación rápida de una etiqueta de imagen al código, se recomienda encarecidamente incluirlos en su esquema de etiquetado.

No almacene secretos en imágenes

Los secretos son información confidencial, como contraseñas, credenciales de bases de datos, claves SSH, tokens y certificados TLS, por nombrar algunos. Estos no deben integrarse en sus imágenes sin cifrarse, ya que los usuarios no autorizados que obtienen acceso a la imagen pueden simplemente examinar las capas para extraer los secretos.

No agregue secretos a sus Dockerfiles en texto sin formato, especialmente si está enviando las imágenes a un registro público como Docker Hub :

FROM python:3.9-slim

ENV DATABASE_PASSWORD "SuperSecretSauce"

En su lugar, deben inyectarse a través de:

  1. Variables de entorno (en tiempo de ejecución)
  2. Argumentos en tiempo de compilación (en tiempo de compilación)
  3. Una herramienta de orquestación como Docker Swarm (a través de los secretos de Docker) o Kubernetes (a través de los secretos de Kubernetes)

Además, puede ayudar a evitar la filtración de secretos agregando archivos y carpetas secretos comunes a su archivo .dockerignore :

**/.env
**/.aws
**/.ssh

Finalmente, sea explícito acerca de qué archivos se copian en la imagen en lugar de copiar todos los archivos de forma recursiva:

# BAD
COPY . .

# GOOD
copy ./app.py .

Ser explícito también ayuda a limitar el cache-busting.

Variables de entorno

Puede pasar secretos a través de variables de entorno, pero serán visibles en todos los procesos secundarios, contenedores vinculados y registros, así como a través de archivos docker inspect. También es difícil actualizarlos.

$ docker run --detach --env "DATABASE_PASSWORD=SuperSecretSauce" python:3.9-slim

d92cf5cf870eb0fdbf03c666e7fcf18f9664314b79ad58bc7618ea3445e39239


$ docker inspect --format='{{range .Config.Env}}{{println .}}{{end}}' d92cf5cf870eb0fdbf03c666e7fcf18f9664314b79ad58bc7618ea3445e39239

DATABASE_PASSWORD=SuperSecretSauce
PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
LANG=C.UTF-8
GPG_KEY=E3FF2839C048B25C084DEBE9B26995E310250568
PYTHON_VERSION=3.9.7
PYTHON_PIP_VERSION=21.2.4
PYTHON_SETUPTOOLS_VERSION=57.5.0
PYTHON_GET_PIP_URL=https://github.com/pypa/get-pip/raw/c20b0cfd643cd4a19246ccf204e2997af70f6b21/public/get-pip.py
PYTHON_GET_PIP_SHA256=fa6f3fb93cce234cd4e8dd2beb54a51ab9c247653b52855a48dd44e6b21ff28b

Este es el enfoque más sencillo para la gestión de secretos. Si bien no es el más seguro, mantendrá honestas a las personas honestas, ya que brinda una capa delgada de protección, lo que ayuda a mantener los secretos ocultos de los ojos curiosos y errantes.

Pasar secretos al usar un volumen compartido es una mejor solución, pero deben estar encriptados a través de Vault o AWS Key Management Service (KMS), ya que se guardan en el disco.

Argumentos en tiempo de compilación

Puede pasar secretos en tiempo de compilación usando argumentos en tiempo de compilación , pero serán visibles para aquellos que tengan acceso a la imagen a través de docker history.

Ejemplo:

FROM python:3.9-slim

ARG DATABASE_PASSWORD

Construir:

$ docker build --build-arg "DATABASE_PASSWORD=SuperSecretSauce" .

Si solo necesita usar los secretos temporalmente como parte de la compilación, es decir, claves SSH para clonar un repositorio privado o descargar un paquete privado, debe usar una compilación de varias etapas, ya que el historial del compilador se ignora para las etapas temporales:

# temp stage
FROM python:3.9-slim as builder

# secret
ARG SSH_PRIVATE_KEY

# install git
RUN apt-get update && \
    apt-get install -y --no-install-recommends git

# use ssh key to clone repo
RUN mkdir -p /root/.ssh/ && \
    echo "${PRIVATE_SSH_KEY}" > /root/.ssh/id_rsa
RUN touch /root/.ssh/known_hosts &&
    ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts
RUN git clone git@github.com:testdrivenio/not-real.git


# final stage
FROM python:3.9-slim

WORKDIR /app

# copy the repository from the temp image
COPY --from=builder /your-repo /app/your-repo

# use the repo for something!

La compilación de varias etapas solo conserva el historial de la imagen final. Tenga en cuenta que puede usar esta funcionalidad para los secretos permanentes que necesita para su aplicación, como una credencial de base de datos.

También puede usar la nueva --secretopción en la compilación de Docker para pasar secretos a las imágenes de Docker que no se almacenan en las imágenes.

# "docker_is_awesome" > secrets.txt

FROM alpine

# shows secret from default secret location:
RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret

Esto montará el secreto del secrets.txtarchivo.

Construye la imagen:

docker build --no-cache --progress=plain --secret id=mysecret,src=secrets.txt .

# output
...
#4 [1/2] FROM docker.io/library/alpine
#4 sha256:665ba8b2cdc0cb0200e2a42a6b3c0f8f684089f4cd1b81494fbb9805879120f7
#4 CACHED

#5 [2/2] RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret
#5 sha256:75601a522ebe80ada66dedd9dd86772ca932d30d7e1b11bba94c04aa55c237de
#5 0.635 docker_is_awesome#5 DONE 0.7s

#6 exporting to image

Finalmente, revisa el historial para ver si el secreto se está filtrando:

❯ docker history 49574a19241c
IMAGE          CREATED         CREATED BY                                      SIZE      COMMENT
49574a19241c   5 minutes ago   CMD ["/bin/sh"]                                 0B        buildkit.dockerfile.v0
<missing>      5 minutes ago   RUN /bin/sh -c cat /run/secrets/mysecret # b…   0B        buildkit.dockerfile.v0
<missing>      4 weeks ago     /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B
<missing>      4 weeks ago     /bin/sh -c #(nop) ADD file:aad4290d27580cc1a…   5.6MB

Para obtener más información sobre los secretos en tiempo de compilación, revise No filtre los secretos de compilación de la imagen de Docker .

Secretos de Docker

Si usa Docker Swarm , puede administrar secretos con Docker secrets .

Por ejemplo, inicie el modo Docker Swarm:

$ docker swarm init

Cree un secreto docker:

$ echo "supersecretpassword" | docker secret create postgres_password -
qdqmbpizeef0lfhyttxqfbty0

$ docker secret ls
ID                          NAME                DRIVER    CREATED         UPDATED
qdqmbpizeef0lfhyttxqfbty0   postgres_password             4 seconds ago   4 seconds ago

Cuando a un contenedor se le da acceso al secreto anterior, se montará en /run/secrets/postgres_password. Este archivo contendrá el valor real del secreto en texto sin formato.

¿Utiliza una herramienta de organización diferente?

  1. AWS EKS: uso de secretos de AWS Secrets Manager con Kubernetes
  2. DigitalOcean Kubernetes: pasos recomendados para proteger un clúster de Kubernetes de DigitalOcean
  3. Google Kubernetes Engine: uso de Secret Manager con otros productos
  4. Nomad: integración de bóveda y recuperación de secretos dinámicos

Usar un archivo .dockerignore

Ya hemos mencionado el uso de un archivo .dockerignore varias veces. Este archivo se usa para especificar los archivos y las carpetas que no desea que se agreguen al contexto de compilación inicial enviado al demonio de Docker, que luego compilará su imagen. Dicho de otra manera, puede usarlo para definir el contexto de compilación que necesita.

Cuando se crea una imagen de Docker, todo el contexto de Docker, es decir, la raíz de su proyecto, se envía al daemon de Docker antes de que se evalúen los comandos COPYo . ADDEsto puede ser bastante costoso, especialmente si tiene muchas dependencias, archivos de datos grandes o crea artefactos en su proyecto. Además, la CLI de Docker y el daemon pueden no estar en la misma máquina. Por lo tanto, si el demonio se ejecuta en una máquina remota, debe tener aún más en cuenta el tamaño del contexto de compilación.

¿Qué debe agregar al archivo .dockerignore ?

  1. Archivos y carpetas temporales
  2. Crear registros
  3. Secretos locales
  4. Archivos de desarrollo local como docker-compose.yml
  5. Carpetas de control de versiones como ".git", ".hg" y ".svn"

Ejemplo:

**/.git
**/.gitignore
**/.vscode
**/coverage
**/.env
**/.aws
**/.ssh
Dockerfile
README.md
docker-compose.yml
**/.DS_Store
**/venv
**/env

En resumen, un .dockerignore correctamente estructurado puede ayudar:

  1. Disminuir el tamaño de la imagen de Docker
  2. Acelerar el proceso de construcción
  3. Evite la invalidación innecesaria de caché
  4. Prevenir la filtración de secretos

Lint y escanear sus Dockerfiles e imágenes

Linting es el proceso de verificar su código fuente en busca de errores programáticos y estilísticos y malas prácticas que podrían conducir a fallas potenciales. Al igual que con los lenguajes de programación, los archivos estáticos también se pueden limar. Específicamente con sus Dockerfiles, los linters pueden ayudar a garantizar que se puedan mantener, evitar la sintaxis obsoleta y adherirse a las mejores prácticas. Delinear sus imágenes debe ser una parte estándar de sus canalizaciones de CI.

Hadolint es el linter de Dockerfile más popular:

$ hadolint Dockerfile

Dockerfile:1 DL3006 warning: Always tag the version of an image explicitly
Dockerfile:7 DL3042 warning: Avoid the use of cache directory with pip. Use `pip install --no-cache-dir <package>`
Dockerfile:9 DL3059 info: Multiple consecutive `RUN` instructions. Consider consolidation.
Dockerfile:17 DL3025 warning: Use arguments JSON notation for CMD and ENTRYPOINT arguments

Puede verlo en acción en línea en https://hadolint.github.io/hadolint/ . También hay una extensión de código VS.

Puede emparejar sus Dockerfiles con escaneo de imágenes y contenedores en busca de vulnerabilidades.

Algunas opciones:

  1. Snyk es el proveedor exclusivo de análisis de vulnerabilidades nativas para Docker. Puede usar el docker scancomando CLI para escanear imágenes.
  2. Trivy se puede usar para escanear imágenes de contenedores, sistemas de archivos, repositorios git y otros archivos de configuración.
  3. Clair es un proyecto de código abierto utilizado para el análisis estático de vulnerabilidades en contenedores de aplicaciones.
  4. Anchore es un proyecto de código abierto que proporciona un servicio centralizado para la inspección, el análisis y la certificación de imágenes de contenedores.

En resumen, deslinte y escanee sus Dockerfiles e imágenes para descubrir cualquier problema potencial que se desvíe de las mejores prácticas.

Firmar y verificar imágenes

¿Cómo sabe que las imágenes utilizadas para ejecutar su código de producción no han sido manipuladas?

La manipulación puede venir a través del cable a través de ataques man-in-the-middle (MITM) o desde que el registro se ve comprometido por completo.

Docker Content Trust (DCT) permite firmar y verificar imágenes de Docker desde registros remotos.

Para verificar la integridad y autenticidad de una imagen, establezca la siguiente variable de entorno:

DOCKER_CONTENT_TRUST=1

Ahora, si intenta extraer una imagen que no ha sido firmada, recibirá el siguiente error:

Error: remote trust data does not exist for docker.io/namespace/unsigned-image:
notary.docker.io does not have trust data for docker.io/namespace/unsigned-image

Puede obtener información sobre la firma de imágenes en la documentación Firma de imágenes con Docker Content Trust .

Al descargar imágenes de Docker Hub, asegúrese de usar imágenes oficiales o imágenes verificadas de fuentes confiables. Los equipos más grandes deberían considerar el uso de su propio registro interno de contenedores privados .

Consejos de bonificación

Uso de entornos virtuales de Python

¿Deberías usar un entorno virtual dentro de un contenedor?

En la mayoría de los casos, los entornos virtuales son innecesarios siempre que se limite a ejecutar un solo proceso por contenedor. Dado que el contenedor en sí proporciona aislamiento, los paquetes se pueden instalar en todo el sistema. Dicho esto, es posible que desee utilizar un entorno virtual en una compilación de varias etapas en lugar de crear archivos de rueda.

Ejemplo con ruedas:

# temp stage
FROM python:3.9-slim as builder

WORKDIR /app

ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

RUN apt-get update && \
    apt-get install -y --no-install-recommends gcc

COPY requirements.txt .
RUN pip wheel --no-cache-dir --no-deps --wheel-dir /app/wheels -r requirements.txt


# final stage
FROM python:3.9-slim

WORKDIR /app

COPY --from=builder /app/wheels /wheels
COPY --from=builder /app/requirements.txt .

RUN pip install --no-cache /wheels/*

Ejemplo con virtualenv:

# temp stage
FROM python:3.9-slim as builder

WORKDIR /app

ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

RUN apt-get update && \
    apt-get install -y --no-install-recommends gcc

RUN python -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"

COPY requirements.txt .
RUN pip install -r requirements.txt


# final stage
FROM python:3.9-slim

COPY --from=builder /opt/venv /opt/venv

WORKDIR /app

ENV PATH="/opt/venv/bin:$PATH"

Establecer límites de memoria y CPU

Es una buena idea limitar el uso de memoria de sus contenedores Docker, especialmente si ejecuta varios contenedores en una sola máquina. Esto puede evitar que cualquiera de los contenedores use toda la memoria disponible y, por lo tanto, paralice el resto.

La forma más fácil de limitar el uso de la memoria es usar --memoryy --cpuopciones en la CLI de Docker:

$ docker run --cpus=2 -m 512m nginx

El comando anterior limita el uso del contenedor a 2 CPU y 512 megabytes de memoria principal.

Puede hacer lo mismo en un archivo Docker Compose así:

version: "3.9"
services:
  redis:
    image: redis:alpine
    deploy:
      resources:
        limits:
          cpus: 2
          memory: 512M
        reservations:
          cpus: 1
          memory: 256M

Toma nota del reservationscampo. Se utiliza para establecer un límite suave, que tiene prioridad cuando la máquina host tiene poca memoria o recursos de CPU.

Recursos adicionales:

  1. Opciones de tiempo de ejecución con memoria, CPU y GPU
  2. Restricciones de recursos de Docker Compose

Iniciar sesión en stdout o stderr

Las aplicaciones que se ejecutan dentro de sus contenedores Docker deben escribir mensajes de registro en la salida estándar (stdout) y el error estándar (stderr) en lugar de en un archivo.

A continuación, puede configurar el demonio de Docker para enviar sus mensajes de registro a una solución de registro centralizada (como CloudWatch Logs o Papertrail ).

Para obtener más información, consulte Tratar registros como flujos de eventos de la aplicación Twelve-Factor y Configurar controladores de registro de los documentos de Docker.

Usar una montura de memoria compartida para Gunicorn Heartbeat

Gunicorn utiliza un sistema de latidos basado en archivos para garantizar que todos los procesos de trabajo bifurcados estén activos.

En la mayoría de los casos, los archivos de latidos se encuentran en "/tmp", que a menudo se encuentra en la memoria a través de tmpfs . Dado que Docker no aprovecha tmpfs de forma predeterminada, los archivos se almacenarán en un sistema de archivos respaldado por disco. Esto puede causar problemas , como bloqueos aleatorios ya que el sistema de latidos utiliza os.fchmod, lo que puede bloquear a un trabajador si el directorio está en un sistema de archivos respaldado por disco.

Afortunadamente, hay una solución simple: cambie el directorio de latidos a un directorio mapeado en memoria a través de la --worker-tmp-dirbandera.

gunicorn --worker-tmp-dir /dev/shm config.wsgi -b 0.0.0.0:8000

Conclusión

Este artículo analizó varias prácticas recomendadas para hacer que sus Dockerfiles e imágenes sean más limpios, eficientes y seguros.

Fuente:  https://testdriven.io

#python #docker 

joe biden

1615785369

Converta e-mails EML para Adobe PDF com o conversor de EML para PDF

Para converter arquivos EML em formato PDF, o Datavare é o aplicativo mais adequado. O aplicativo oferece muitas vantagens para que os usuários possam converter os arquivos facilmente. Isso ajuda a fazer uma conversão direta. O aplicativo é mais adequado para cada usuário e, portanto, converte os arquivos EML de uma forma precisa e sem erros. Qualquer usuário pode fazer a conversão de arquivos EML para o formato PDF, pois o aplicativo é muito fácil de operar. Usuários sem formação técnica também podem usar este aplicativo incrível sem qualquer problema.

Embora o aplicativo seja muito avançado, ainda assim, com sua interface gráfica amigável, é fácil converter arquivos EML para o formato PDF. Para tal não é necessária qualquer tipo de assistência técnica. A tarefa de conversão é fácil e simples de fazer com este aplicativo de terceiros. É um aplicativo altamente compatível que funciona perfeitamente em qualquer versão do Windows. Para usar o aplicativo, não é necessário que a versão do Windows seja a mais recente ou a mais antiga.

Além disso, há muitas vantagens em usar esse aplicativo notável. Vamos falar sobre algumas dessas vantagens que ela confere:

  • Concede conversão direta
  • Transfere arquivos em alta velocidade
  • Sem restrição de tamanho
  • Aplicação independente
  • Conversão sem erros

Essas vantagens tornam o aplicativo mais adequado para uso. Vale a pena usar este aplicativo para converter arquivos EML em formato PDF. Baixe sua versão de teste agora.

Passos para conversão

Para continuar a tarefa de conversão, é necessário seguir alguns passos. O processo de conversão ocorre em um processo passo a passo. Essas etapas são muito fáceis de executar por qualquer usuário. Não há necessidade de nenhuma orientação técnica para auxiliar essas etapas.

Agora, vamos apenas dar uma olhada nessas etapas simples, depois de baixar e iniciar o aplicativo;
Passo 1- Abra o aplicativo e escolha os arquivos EML que você deseja apenas converter.
Etapa 2 - Escolha o local onde deseja salvar os arquivos convertidos.
Etapa 3- Clique no botão converter agora.

Com essas 3 etapas fáceis, você pode converter seus arquivos EML em formato PDF.

Essas etapas são muito fáceis, e o aplicativo também fornece instantâneos adequados das etapas fornecidas para a assistência adequada do usuário. Além disso, uma interface de usuário fácil é fornecida pelo aplicativo para oferecer suporte a seus usuários. Em primeiro lugar, use a versão demo do aplicativo.

Características principais

Com muitas vantagens, o aplicativo também disponibiliza alguns recursos fundamentais aos seus usuários para a melhor conversão dos arquivos EML. Vejamos alguns desses recursos:

Conversão perfeita
Com uma velocidade rápida, é imprescindível que seus arquivos sejam convertidos na perfeição, sem nenhuma alteração dos dados. Este aplicativo é adequado para converter seus dados na perfeição.

Conversão seletiva
É necessário que os arquivos que você escolher sejam os que somente devem ser convertidos. Portanto, este aplicativo inteligente converte apenas os arquivos que você seleciona para a conversão. Não, outros arquivos EML são convertidos para o formato PSF.

Conversão em lote
Os dados que você escolher são convertidos em lotes. Isso significa que você pode escolher os arquivos que deseja converter ou pode escolher a pasta. Somando-se a isso, a filtragem de arquivos é fornecida no modo de arquivo

Salve os dados de acordo
Você pode escolher os arquivos a serem convertidos, bem como o local. O aplicativo oferece suporte ao salvamento personalizado de dados. Isso significa que, sem qualquer obrigação, você pode salvar seus dados de forma fácil e adequada. Esses recursos fornecem um resultado proveitoso para os usuários.

Declaração final

Os usuários podem baixar o EML para PDF Converter para converter seus arquivos EML para o formato PD. O aplicativo é fácil de usar em qualquer versão do Windows. O usuário pode converter quantos arquivos quiser sem qualquer obrigação, uma vez que adquira a versão licenciada do aplicativo.

Recursos como conversão em alta velocidade, excelente precisão e grande compatibilidade tornam o uso do aplicativo mais útil. Este aplicativo independente executa a tarefa de conversão diretamente sem qualquer problema. Portanto, experimente a versão demo gratuita do aplicativo agora e examine-o convertendo seus poucos arquivos EML em formato PDF.
Se você enfrentar algum tipo de problema também pode entrar em contato com o número de atendimento ao cliente fornecido pelo aplicativo ao seu usuário. Este serviço de ajuda ao cliente está disponível 24 horas por dia, 7 dias por semana.

Mais informações:- https://www.datavare.com/software/eml-to-pdf-converter-expert.html

#conversor de eml para pdf #migração de eml para pdf #exportador de eml para pdf #converter eml para pdf #importar eml para pdf

Art  Lind

Art Lind

1602968400

Python Tricks Every Developer Should Know

Python is awesome, it’s one of the easiest languages with simple and intuitive syntax but wait, have you ever thought that there might ways to write your python code simpler?

In this tutorial, you’re going to learn a variety of Python tricks that you can use to write your Python code in a more readable and efficient way like a pro.

Let’s get started

Swapping value in Python

Instead of creating a temporary variable to hold the value of the one while swapping, you can do this instead

>>> FirstName = "kalebu"
>>> LastName = "Jordan"
>>> FirstName, LastName = LastName, FirstName 
>>> print(FirstName, LastName)
('Jordan', 'kalebu')

#python #python-programming #python3 #python-tutorials #learn-python #python-tips #python-skills #python-development

Art  Lind

Art Lind

1602666000

How to Remove all Duplicate Files on your Drive via Python

Today you’re going to learn how to use Python programming in a way that can ultimately save a lot of space on your drive by removing all the duplicates.

Intro

In many situations you may find yourself having duplicates files on your disk and but when it comes to tracking and checking them manually it can tedious.

Heres a solution

Instead of tracking throughout your disk to see if there is a duplicate, you can automate the process using coding, by writing a program to recursively track through the disk and remove all the found duplicates and that’s what this article is about.

But How do we do it?

If we were to read the whole file and then compare it to the rest of the files recursively through the given directory it will take a very long time, then how do we do it?

The answer is hashing, with hashing can generate a given string of letters and numbers which act as the identity of a given file and if we find any other file with the same identity we gonna delete it.

There’s a variety of hashing algorithms out there such as

  • md5
  • sha1
  • sha224, sha256, sha384 and sha512

#python-programming #python-tutorials #learn-python #python-project #python3 #python #python-skills #python-tips