2016-09-23 1 views
2

Je développe une API avec Rust et gère les environnements, y compris la base de données externe avec Docker. Chaque fois que je fais une modification au code de l'API, la cargaison se reconstruit, et puisque Docker ne cache rien à faire avec l'instruction ADD pour copier le répertoire Rust sur le conteneur, il télécharge tous les paquets, ce qui est assez processus long puisque j'utilise Nickel, qui semble avoir une cargaison de dépendances.Optimisation des temps de génération de fret dans Docker

Existe-t-il un moyen d'intégrer ces dépendances avant d'exécuter cargo build? Au moins de cette façon, si les dépendances changent, elle n'installera que ce qui est requis, similaire à la compilation de Cargo localement.

Voici le Dockerfile J'utilise actuellement:

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 

Et voici mon 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"] } 
+1

Peut-être que vous pouvez d'abord ajouter et compiler une application fictive avec les mêmes dépendances. – wimh

+1

https://github.com/rust-lang/cargo/issues/1891. Notez également que vous pouvez installer la chaîne d'outils correcte en une seule étape './rustup.sh -y --default-toolchain 1.11.0' – Shepmaster

Répondre

3

Docker ne cache la couche construite à partir du ADD (de préférence COPY) instruction , à condition que les sources n'aient pas changé. Vous pouvez utiliser cela et mettre vos dépendances en cache en copiant le Cargo.toml en premier, et en faisant une compilation.

Mais malheureusement, vous avez besoin quelque chose à construire, pour que vous puissiez le faire avec un seul fichier source et une cible lib factice dans votre manifeste:

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

Dans votre Dockerfile construire séparément le mannequin:

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

La sortie de cette couche sera mise en cache, avec toutes les dépendances installées, et vous pourrez ensuite ajouter le reste de votre code (dans le même Dockerfile):

COPY /src/ app/src/ 
RUN cargo build 

Le truc dummy est laid, mais cela signifie que votre construction normale sera rapide, car il vient de la couche en cache, et lorsque vous modifiez les dépendances dans votre Cargo.toml puis Docker va le ramasser et construire une nouvelle couche avec mise à jour dépendances.

+1

* copier le 'Cargo.toml' en premier * - ** et ** le' Cargo.lock'! – Shepmaster

+0

J'ai utilisé avec succès cette technique avec des projets Ruby, en copiant dans 'Gemfile' /' Gemfile.lock' et en exécutant 'bundle install'. – Shepmaster

+0

Pourquoi "COPY" et non "ADD"? –

-1

Vous pouvez créer une image intermédiaire et construire votre image finale de celui-ci. Par exemple:

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

construction en utilisant 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 cette façon, seul le mybaseimage est reconstruit

0

Au lieu d'ajouter un fichier fictif, vous pouvez également laisser construire l'échec:

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

Ne pas oublier d'ajouter --release aux deux endroits si vous voulez optimized construit.

+0

Je dois encore copier 'cargo.lock' et' cargo.toml', n'est-ce pas? – BonsaiOak

+0

C'est correct. – khc