Docker multi-stage

Docker multi-stage

Elävän elämän esimerkki Dockerin multi-stage-käännöksen eduista

Multi-stage on Dockerin tapa suorittaa näköistiedoston luonti vaiheittain siten, etteivät eri vaiheiden toimenpiteet vaikuta muihin vaiheisiin.

Joku aika sitten raportoin Gambit Scheme -ohjelmointityökaluista löytyneen bugin projektin ylläpidolle. Bugi korjattiin nopeasti, mutta korjaus tuli varsinaiseen julkaisuversioon mukaan vasta myöhemmin. Halusin testata ja kuitata bugin korjatuksi julkaistulla versiolla. Harmillisesti julkaisusta ei ollut missään millekään alustalle valmiita asennuspaketteja tarjolla, joten päätin kääntää projektin itse. Hommassa oli kuitenkin pari haastetta. Ensinnäkin, enhän vielä tiennyt, joudunko testaamaan useampaa versiota, jos bugia ei olekaan korjattu kunnolla. En halunnut sotkea konettani käännöstyökaluilla ja mahdollisesti useammalla käännetyllä Gambit-paketilla. Toisekseen en halunnut myöskään saastuttaa itse Gambit-asennusta käännöstyökaluilla ja -kirjastoilla. Halusin tarkistaa bugikorjauksen puhtaalla oikeaoppisesti asennetulla versiolla.

Ensimmäisen haasteen Docker taklaa hienosti. Tekee vain näköistiedoston, jossa ovat kaikki tarvittavat kirjastot ja käännöstyökalut sekä projektin lähdekoodien oikea versio. Toisen haasteen taklaaminen onkin sitten hankalampaa. Pitääkö käännöstyökalut, käännökset ja lähdekoodit siivota pois näköistiedostosta vai kopioida asennuspaketti toiseen Docker-näköistiedostoon? Tähän työläältä vaikuttavaan haasteeseen Docker tarjoaa multi-stage-käännöksen.

Valmis Dockerfile näyttää tältä:

FROM ubuntu:22.10

ENV TZ=Europe/Helsinki

RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

RUN apt update && \
apt install -y build-essential git

WORKDIR /build
RUN git clone --depth 1 --branch v4.9.4 https://github.com/gambit/gambit.git

WORKDIR gambit
RUN ./configure --enable-single-host --enable-march=native --enable-dynamic-clib --prefix=/usr/local
RUN make -j8
RUN make check
RUN make install

FROM ubuntu:22.10
COPY --from=0 /usr/local /usr/local
CMD ["gsi", "-:s"]
  1. Pohjaksi otetaan Dockerhubista Ubuntun versio 22.10
  2. Tehdään pari taikatemppua aikavyöhykkeiden kanssa, ettei apt-komennon ajaminen aiheuta turhia harmaita hiuksia.
  3. Asennetaan apt-komennolla käännöstyökalut ja git
  4. Laitetaan työhakemisto osoittamaan kansioon /build. Tämän kansion alle tullaan kloonaamaan projektin lähdekoodit.
  5. Kloonataan haluttu versio Gambitin lähdekoodista. Tässä tapauksessa versio on tagilla “v.4.9.4” ja lisäksi antamalla “–depth 1”, kloonaamme vain kyseisen version, emme muuta versiohistoriaa.
  6. Git kloonaa lähdekoodit projektin nimen mukaiseen kansioon, joten vaihdetaan työhakemisto “gambit”-kansioksi.
  7. Suoritetaan Gambitin vaatimat käännös- ja asennusloitsut. Määritellään asennuskansioksi /usr/local.

Tähän asti tuttua ja turvallista Docker-tavaraa. Kääntämällä Docker-näköistiedoston edellä kuvattujen askelten avulla, saisimme näköistiedoston, joka sisältää kaikki käännöskirjastot ja työkalut sekä Gambitin lähdekoodit, objektitiedostot ja asennetun Gambitin /usr/local-kansiossa.

Tehdään tästä Dockerfilestä multi-stage lisäämällä uusi FROM-rivi kaiken edellä olleen jatkoksi. Tämä on signaali Dockerille suorittaa käännös monivaiheisesti.

  1. Kuten edellä, käytetään pohjana Ubuntu 22.10-versiota
  2. Kopioidaan edellisen vaiheen (stage 0) näköistiedostosta /usr/local-kansion sisältö tähän uuteen näköistiedostoon kansioon /usr/local. Docker tietää tehdä kopioinnin näköistiedostosta toiseen nähdessään määreen: “–from=0”.
  3. Määritellään lopuksi komento, joka ajetaan, kun tästä näköistiedostosta käynnistetään uusi kontti. Komentorivi “gsi -:s” on Gambit-spesifi komento, joka käynnistää interaktiivisen komentorivitulkin ja lataa tietyt kirjastot automaattisesti, jotka ovat keskeisiä testauksen kannalta.

Edellä oleva Dockerfile käännetään kuten mikä tahansa muu Dockerfile komentamalla:

docker build -t gambit:4.9.4 .

Lopputuloksena pitäisi olla suhteellisen pienikokoinen näköistiedosto:

REPOSITORY  TAG    IMAGE ID      CREATED         SIZE
gambit      4.9.4  1e421b726dbd  24 minutes ago  220MB

Tämä näköistiedosto ei sisällä mitään ensimmäisen vaiheen kehitystyökaluja, kirjastoja, lähdekoodeja tai käännöksestä jääneitä objekteja. Paketissa on vain perus-Ubuntu-pohja sekä /usr/local-kansiossa tuore käännös Gambitista.

Nyt testaus voi alkaa yksinkertaisesti komentamalla:

docker run -it --rm gambit:4.9.4

Lisätietoa Dockerin multi-stage-käännöksistä voi lukea täältä: Multi-stage builds (at docker.com)

Kirjoittaja on Ouron Senior Developer Matti Kärki

Edellinen artikkeli
Productivity Paranoia
Seuraava artikkeli
Dockerin tagit lyhyesti