tag run remove hub example docker dependencies rust rust-cargo

run - docker tag example



Optimizar los tiempos de construcción de carga en Docker (3)

Estoy desarrollando una API con Rust y estoy administrando los entornos, incluida la base de datos externa con Docker. Cada vez que realizo un cambio en el código API, la carga se reconstruye, y como Docker no guarda nada en la declaración ADD para copiar el directorio Rust en el contenedor, vuelve a descargar todos los paquetes, lo que es bastante proceso largo ya que estoy usando Nickel, que parece tener un montón de dependencias.

¿Hay alguna forma de incorporar esas dependencias antes de ejecutar cargo build ? Al menos, si las dependencias cambian, solo instalará lo que se requiere, similar a la compilación de carga local.

Aquí está el archivo Docker que uso actualmente:

FROM ubuntu:xenial RUN apt-get update && apt-get install curl build-essential ca-certificates file xutils-dev nmap -y RUN mkdir /rust WORKDIR /rust RUN curl https://sh.rustup.rs -s >> rustup.sh RUN chmod 755 /rust/rustup.sh RUN ./rustup.sh -y ENV PATH=/root/.cargo/bin:$PATH SSL_VERSION=1.0.2h RUN rustup default 1.11.0 RUN curl https://www.openssl.org/source/openssl-$SSL_VERSION.tar.gz -O && / tar -xzf openssl-$SSL_VERSION.tar.gz && / cd openssl-$SSL_VERSION && ./config && make depend && make install && / cd .. && rm -rf openssl-$SSL_VERSION* ENV OPENSSL_LIB_DIR=/usr/local/ssl/lib / OPENSSL_INCLUDE_DIR=/usr/local/ssl/include / OPENSSL_STATIC=1 RUN mkdir /app WORKDIR /app ADD . /app/ RUN cargo build EXPOSE 20000 CMD ./target/debug/api

Y aquí está mi Cargo.toml

[profile.dev] debug = true [package] name = "api" version = "0.0.1" authors = ["Vignesh Sankaran <[email protected]>"] [dependencies] nickel = "= 0.8.1" mongodb = "= 0.1.6" bson = "= 0.3.0" uuid = { version = "= 0.3.1", features = ["v4"] }


Docker almacena en caché la capa creada a partir de la instrucción ADD (preferiblemente COPY ), siempre que las fuentes no hayan cambiado. Puede hacer uso de eso y obtener sus dependencias en caché copiando Cargo.toml primero y haciendo una compilación.

Pero, lamentablemente, necesitas algo para compilar, por lo que puedes hacerlo con un único archivo fuente y un objetivo ficticio lib en tu manifiesto:

[lib] name = "dummy" path = "dummy.rs"

En tu archivo Docker, crea el dummy por separado:

COPY Cargo.toml /app/Cargo.toml COPY dummy.rs /app/dummy.rs RUN cargo build --lib

La salida de esta capa se almacenará en caché, con todas las dependencias instaladas, y luego podrá continuar agregando el resto de su código (en el mismo Dockerfile ):

COPY /src/ app/src/ RUN cargo build

Las cosas dummy son feas, pero significa que tu compilación normal será rápida, ya que proviene de la capa en caché, y cuando cambias las dependencias en tu Cargo.toml , Docker lo levantará y construirá una nueva capa con dependencias actualizadas.


Puede crear una imagen intermedia y crear su imagen final a partir de ella. P.ej:

FROM ubuntu:xenial RUN apt-get update && apt-get install curl build-essential ca-certificates file xutils-dev nmap -y RUN mkdir /rust ...

construir usando la construcción de docker build -t mybaseimage .

FROM mybaseimage RUN mkdir /app WORKDIR /app ADD . /app/ RUN cargo build EXPOSE 20000 CMD ./target/debug/api

docker build -t finalimage .

De esa forma solo se reconstruye la imagen mybase


En lugar de agregar un archivo ficticio, también puede dejar que falle la compilación:

RUN cargo build || true COPY ... RUN cargo build

No olvides agregar --release a ambos lugares si quieres compilaciones optimizadas.