--- author: Matija Burić --- ### Mrežni i mobilni operacijski sustavi 2025/26 # Kontejnerizacija: Dockerfile Ova vježba fokusira se na Dockerfile, ključni sastojak za izgradnju prilagođenih Docker kontejnera. U nastavku ćemo se upoznati s osnovama Dockerfile-a i detaljnije razumjeti koncept Dockerfile slojeva. ## Što je Dockerfile? Dockerfile je tekstualna datoteka koja sadrži niz instrukcija za izgradnju Docker kontejnera. Svaka instrukcija u Dockerfile-u predstavlja jedan korak u procesu izgradnje. Pomoću Dockerfile-a možemo definirati okolinu, postavke, ovisnosti i aplikacijski kod koji će biti dio našeg kontejnera. Dockerfile je ključan za reproduktivnost i skalabilnost aplikacija jer omogućuje definiranje svega što je potrebno za pokretanje aplikacije unutar kontejnera. ## Slojevi u Dockerfile-u Jedinstvena značajka Dockerfile-a je koncept "slojeva". Slojevi čine temeljni građevni blok Docker image-a. Svaka instrukcija u Dockerfile-u stvara novi sloj koji se dodaje na postojeći image. Kada se promjena dogodi u jednom sloju, samo taj sloj se ponovno izgradi, dok svi prethodni slojevi ostaju nepromijenjeni, osim ako ih eksplicitno mijenjamo. Ova arhitektura omogućuje efikasno korištenje resursa i brze promjene. Slojevi se mogu ponovno koristiti između različitih image-a, što smanjuje potrošnju prostora na disku i ubrzava proces izgradnje. ### Zašto su Slojevi Važni? Slojevi imaju nekoliko ključnih prednosti: - **Reproduktivnost**: stvaranje identičnih kontejnera - **Upravljanje verzijama**: novi Dockerfile = nova verzija - **Dokumentacija**: jasno opisuje postupak konfiguracije - **Dijeljenje**: jednostavno dijeljenje s drugima ## Dockerfile primjena Rad s Dockerfile-om uključuje definiranje potrebnih slojeva za vaš kontejner. Svaki sloj može uključivati instalaciju paketa, kopiranje datoteka, postavljanje okoline i mnoge druge operacije. Upravljanje slojevima ključno je za optimizaciju vašeg Docker image-a. ## Osnovni minimalni Dockerfile ### Primjer Ovaj Dockerfile demonstrira minimalnu konfiguraciju potrebnu za izgradnju Docker kontejnera. U ovom primjeru, izgradit ćemo jednostavan kontejner koji koristi službeni image za Python i ispisuje poruke na standardni izlaz. #### Predkoraci - napravite direktorij na računalu i pozicionirajte se u njega. - otvorite editor za python (IDE ili bilo koji tekst editor) i kopirajte slijedeći kod te snimite dokument sa imenom i nastavkom `app.py` :::info ako koristite https://labs.play-with-docker.com/ kombinacija tipki za: copy > Ctrl + Insert paste > Shift + Insert ::: ```python import random # Lista različitih pozdrava greetings = [ "Avokado je voće, ne povrće", "Eiffel-ov toranj je ljeti viši za 15 cm!", "Australija je šira nego mjesec!", "Venera se okreće u krivome smjeru!", "Glave s uskršnjih otoka imaju tjela!", "Ne možeš poljubiti svoj lakat!", ] # Nasumično odaberi pozdrav iz liste selected_greeting = random.choice(greetings) # Ispis pozdrava print(selected_greeting) ``` - opet otvorite editor za tekst, nazovite dokument `DockerFile` bez nastavka te slijedite korake i kopirajte pojedine linije koda. #### Korak 1: Odabir Baznog Image-a ```dockerfile FROM python:3.9-slim ``` - `FROM python:3.9-slim` linija određuje da ćemo koristiti Python 3.9-slim kao bazni image za naš kontejner. :::info Obratite pažnju na to da odaberete verziju image-a koji ćete koristiti. Ukoliko nije odabrana verzija, preuzeti će se zadnja (latest) verzija. To u pravilu nije preporučeno. ::: #### Korak 2: Dodavanje Aplikacijskog Koda ```dockerfile COPY app.py /app.py ``` - `COPY app.py /app.py` linija kopira datoteku `app.py` s vašeg lokalnog računala u korijenski direktorij kontejnera pod nazivom `/app.py`. #### Korak 3: Postavljanje Radnog Direktorija ```dockerfile WORKDIR / ``` - `WORKDIR /` linija postavlja radni direktorij kontejnera na korijenski direktorij. :::info Postavljanje radnog direktorija (WORKDIR) u Dockerfile-u ima nekoliko važnih prednosti i koristi: - **Organizacija**: Postavljanjem radnog direktorija možete organizirati strukturu direktorija unutar vašeg kontejnera. To olakšava upravljanje datotekama i resursima unutar kontejnera. - **Čitljivost**: Postavljanje radnog direktorija čini Dockerfile čitljivijim jer jasno pokazuje u kojem direktoriju se izvršavaju sljedeće naredbe. To pomaže drugim razvojnicima da razumiju strukturu vašeg kontejnera. - **Relativne putanje**: Kada postavite radni direktorij, možete koristiti relativne putanje u Dockerfile-u. To čini Dockerfile prenosivim jer ne ovisi o apsolutnim putanjama na host sustavu. - **Lakše održavanje**: Postavljanjem radnog direktorija možete izbjeći nepotrebno prebacivanje između direktorija u kontejneru. To olakšava održavanje i smanjuje mogućnost grešaka. - **Izolacija**: Kada se postavi radni direktorij, naredbe koje slijede će se izvoditi u okviru tog direktorija. To pomaže u izoliranju i ograničavanju utjecaja naredbi na druge dijelove kontejnera. Primjena postavljanja radnog direktorija ovisi o specifičnostima vašeg Dockerfile-a i vašim potrebama. U mnogim slučajevima, postavljanje radnog direktorija poboljšava organizaciju i čitljivost Dockerfile-a, što olakšava izradu, održavanje i dijeljenje Docker kontejnera. ::: #### Korak 4: Definiranje Naredbe za Izvođenje ```dockerfile CMD ["python", "app.py"] ``` - `CMD ["python", "app.py"]` linija definira naredbu koja će se izvršiti prilikom pokretanja kontejnera. U ovom slučaju, pokrenuti će se python koji će pokrenuti app.py datoteku. #### Korak 5: izgradite image ```bash docker build . ``` - `docker build .` će se pozicionirati u direktorij u kojem se nalazite i pokrenuti izgradnju image-a. Ako prvi puta povlačite `python:3.9-slim` image onda će izgradnja potrajati dok se cijeli image ne spusti lokalno. Po završetku dobiti ćete izlaz poput navedenog: ```shell $ docker build . [+] Building 488.2s (7/7) FINISHED docker:default => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 259B 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [internal] load metadata for docker.io/library/python:3.9 0.8s => [internal] load build context 0.0s => => transferring context: 28B 0.0s => [1/3] FROM docker.io/library/python:3.9@sha256:031b2 ... 479.9s => => resolve docker.io/library/python:3.9@sha256:031b2 ... 0.0s => => sha256:167b8a53ca4504b ... 49.56MB / 49.56MB 166.5s => => sha256:b47a222d28fa956 ... 24.03MB / 24.03MB 88.7s ... => [2/3] COPY app.py /app.py 7.3s => exporting to image 0.1s => => exporting layers 0.0s => => writing image sha256:a2fe8f5d174f169e2ca9441 ... 0.0s ``` - što se sve može uočiti iz tijeka izrade image-a: - slojevi novo izgrađenog image-a, - vrijeme izrade po pojedinom sloju, - veličina prilikom prijenosa, - ime osnovnog image-a, - naredba kopiranja podataka. #### Korak 6: pokretanje kontejnera iz novo izgrađenog image-a ```shell $ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE <none> <none> a2fe8f5d174f 2 minutes ago 997MB alpine latest 8ca4688f4f35 10 days ago 7.34MB ... ``` ```shell $ docker run a2fe8f5d174f Ne možeš poljubiti svoj lakat! ``` :::success Slijedeći gore navedene korake napravili ste svoj prvi image iz kojeg ste pokrenuli svoj kontejner. ::: :::info ### Gdje se nalaze image-i koje smo povukli? - Nakon što izgradite Docker image koristeći naredbu `docker build`, izgrađeni image će biti dostupan na vašem lokalnom računalu. Docker sprema izgrađene image-e u lokalni Docker registar. Lokacija ovog registra može varirati ovisno o platformi na kojoj koristite Docker. - Tipična mjesta gdje se Docker image-i mogu pohraniti na različitim platformama: - Linux: Ako koristite Docker na Linux sustavu, izgrađeni Docker image će biti pohranjen u direktoriju /var/lib/docker na vašem Linux sistemu. - Windows: Na Windows sustavima, Docker image-i obično se pohranjuju unutar virtualnog Linux okvira (Docker Desktop for Windows koristi Linux VM). Detalji o lokaciji će varirati ovisno o verziji Docker Desktopa. - Ako želite saznati koji su Docker image-i pohranjeni na vašem računalu, možete koristiti naredbu `docker image ls` kako biste vidjeli popis svih dostupnih image-a, uključujući i one koje ste nedavno izgradili. ::: ### Struktura osnovnog minimalnog Dockerfile - Osnovni minimalni Dockerfile sadrži: ```dockerfile FROM base_image:tag COPY source_dir /target_dir WORKDIR /working_directory CMD ["command", "arg1", "arg2"] ``` - `FROM base_image:tag`: Odabire osnovni Docker image iz kojeg će se izgraditi kontejner. **base_image** je naziv osnovnog image-a (primjerice, ubuntu, python, node), a **tag** je verzija tog image-a (primjerice, 18.04, 3.9, 14). - `COPY source_dir /target_dir`: Kopira datoteke iz **source_dir** (na lokalnom računalu) u **/target_dir** unutar kontejnera. - `WORKDIR /working_directory`: Postavlja radni direktorij unutar kontejnera na **/working_directory**. To je direktorij u kojem će se izvršavati naredbe. - `CMD ["command", "arg1", "arg2"]`: Definira naredbu koja će se automatski izvršiti kad se kontejner pokrene. **command** predstavlja izvršnu naredbu (primjerice, python, npm, echo), a **arg1**, **arg2** su argumenti koji se prosljeđuju toj naredbi. ## Proširenje Dockerfile Kroz slijedeće primjere nadograditi ćemo osnovni Dockerfile. Za svaki slijedeći primjer: - kreirajte direktorij, - pozicionirajte se u njega, - stvorite Dockerfile, - prema uputama popunite Dockerfile, - snimite promjene, - kreirajte sliku pomoću slijedeće naredbe: ```shell $ docker build -t [ime]:[tag] . ``` pri čemu umjesto `[ime]` postavite proizvoljno ime, a umjesto `[tag]` postavite verziju. ### Primjer 1 - U primjeru će biti prikazana primjena `RUN`, `ENTERYPOINT` i `CMD` naredbi te njihove razlike. #### Korak 1: postavljanje osnovnog image-a ```dockerfile FROM fedora:39 WORKDIR / CMD ["cat /etc/fedora-release"] ``` - kreirajte image: ```shell! $ docker build -t primjer1:01 . ... ``` - pokrenite kontejner: ```shell! $ docker run primjer1 Unable to find image 'primjer1:latest' locally docker: Error response from daemon: pull access denied for primjer1, repository does not exist or may require 'docker login': denied: requested access to the resource is denied. See 'docker run --help'. ``` :::info Nedostaje verzija. Docker pokušava preuzeti **latest** image koji ne postoji. ::: - ponovo pokrenite kontejner: ```shell! $ docker run primjer1:01 docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "cat /etc/fedora-release": stat cat /etc/fedora-release: no such file or directory: unknown. ``` :::info Sintaksa Dockerfile **CMD** naredbe je krivo napisana. ::: - Ispravite sintaksu i ponovno kreirajte image, te pokrenite kontejner: ```dockerfile! FROM fedora:39 WORKDIR / CMD ["cat", "/etc/fedora-release"] ``` ```shell $ docker run primjer1:02 Fedora release 39 (Thirty Nine) ``` :::success pokrenuti kontejner vraća informaciju o verziji linuxa ::: - ponovo pokrenite kontejner na slijedeći način: ```shell! $ docker run primjer1:02 df Filesystem 1K-blocks Used Available Use% Mounted on overlay 263174212 41486824 208249232 17% / tmpfs 65536 0 65536 0% /dev tmpfs 18455188 0 18455188 0% /sys/fs/cgroup shm 65536 0 65536 0% /dev/shm /dev/sdc 263174212 41486824 208249232 17% /etc/hosts tmpfs 18455188 0 18455188 0% /proc/acpi tmpfs 18455188 0 18455188 0% /sys/firmware ``` :::success uočite da je naredba **df** premostila naredbu **CMD**. ::: #### Korak 2: dodavanje entrypoint-a ```dockerfile FROM fedora:39 WORKDIR / CMD ["figlet"] ``` - kreirajte image - pokrenite kontejner: ```shell! $ docker run primjer1:03 docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "figlet": executable file not found in $PATH: unknown. ``` :::info Nedostaje paket **figlet**. Potrebno ga je instalirati. Dodajte instalaciju prije nego pozivate **figlet**. ::: ```dockerfile! FROM fedora:39 WORKDIR / RUN yum install -y figlet CMD ["figlet"] ``` - kreirajte image - pokrenite kontejner: ```shell! $ docker run primjer1:04 $ ``` :::info Naredba **figlet** ne vraća rezultat jer očekuje ulaznu varijablu. Potrebno je definirati što će **figlet** vratiti. ::: ```dockerfile! FROM fedora:39 WORKDIR / RUN yum install -y figlet CMD ["figlet", "radi li?"] ``` - kreirajte image - pokrenite kontejner: ```shell! $ docker run primjer1:04 _ _ _ _ ___ _ __ __ _ __| (_) | (_)__ \ | '__/ _` |/ _` | | | | | / / | | | (_| | (_| | | | | ||_| |_| \__,_|\__,_|_| |_|_|(_) ``` :::success Pokušajte sada proslijediti tekst koji vama odgovara. ::: ```shell! $ docker run primjer1:04 Super, radi!!! docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "Super,": executable file not found in $PATH: unknown. ``` :::info Dodavanje varijable u terminalu poništava **CMD**. Potrebno je postaviti početnu naredbu koja se neće poništiti. ::: #### Korak 3: pokretanje i provjera konačnog image-a ```dockerfile FROM fedora:39 WORKDIR / RUN yum install -y figlet ENTRYPOINT ["figlet"] CMD ["radi li sada!"] ``` ```shell $ docker run primjer1:04 _ _ _ _ _ _ _ __ __ _ __| (_) | (_) ___ __ _ __| | __ _| | | '__/ _` |/ _` | | | | | / __|/ _` |/ _` |/ _` | | | | | (_| | (_| | | | | | \__ \ (_| | (_| | (_| |_| |_| \__,_|\__,_|_| |_|_| |___/\__,_|\__,_|\__,_(_) ``` ```shell! $ docker run primjer1:04 RADI!!! ____ _ ____ ___ _ _ _ | _ \ / \ | _ \_ _| | | | | |_) | / _ \ | | | | || | | | | _ < / ___ \| |_| | ||_|_|_| |_| \_\/_/ \_\____/___(_|_|_) ``` :::success Kontejner uspješno instalira, pokreće, postavlja početne varijable te dozvoljava unos varijabli. ::: **Usporedba RUN, CMD i ENTRYPOINT:** | Naredba | Opis | |---|:---| | **RUN** | Koristi se za izvršavanje naredbi u kontejneru tijekom izgradnje. Naredbe RUN se izvršavaju u redoslijedu u kojem su navedene u Dockerfileu. | | **CMD** | Koristi se za definiranje naredbi koje će se izvršiti kada se kontejner pokrene. Naredbe CMD se izvršavaju u trenutku pokretanja kontejnera i mogu biti poništene korisničkim upitom. | | **ENTRYPOINT** | Koristi se za definiranje naredbe koja će se izvršiti kada se kontejner pokrene. Naredbe ENTRYPOINT se ne mogu prebrisati naredbama CMD. | ### Primjer 2 - U primjeru će biti detaljnije prikazana primjena `RUN` naredbe kao i naredbe `ADD`, `ENV` i `USER`. #### Korak 1: dodavanje dokumenta s udaljene lokacije ```dockerfile FROM ubuntu:latest ENV WEBSITE1=https://i.ebayimg.com/images/g/c-IAAOSwyNVgeYQa/s-l1600.jpg COPY $WEBSITE1 / WORKDIR / CMD ["/bin/bash"] ``` - U ovom primjeru `ENV` varijabla definira URL slike. Ova vrijednost se zatim koristi u naredbi `COPY` za kopiranje slike u image. :::info **ENV** varijable su korisne u sljedećim slučajevima: - **Definiranje postavki**: ENV varijable se mogu koristiti za definiranje postavki koje se mogu koristiti u cijelom imageu. Na primjer, možete koristiti ENV varijablu za definiranje baze podataka koju će image koristiti ili za definiranje portova koji će image koristiti. - **Varijable okoliša**: ENV varijable se mogu koristiti za definiranje varijabli okoliša koje se mogu koristiti u naredbama ili u kodu. Na primjer, možete koristiti ENV varijablu za definiranje ključa API-ja koji će image koristiti ili za definiranje ID-a aplikacije. - **Druge vrijednosti**: ENV varijable se mogu koristiti za definiranje bilo kakve vrijednosti koja se može koristiti u cijelom imageu. Na primjer, možete koristiti ENV varijablu za definiranje imena datoteke koja će image kopirati ili za definiranje imena skripte koja će image pokrenuti. ::: - kreirajte image - pokrenite kontejner: ```shell! $ docker build -t primjer2:01 . [+] Building 0.1s (3/3) FINISHED docker:default => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [internal] load build definition from Dockerfile 0.0s ... Dockerfile:3 -------------------- 1 | FROM ubuntu:latest 2 | ENV WEBSITE1=https://i.ebayimg.com/images/g/c-IAAOSwyNVgeYQa/s-l1600.jpg 3 | >>> COPY $WEBSITE1 / 4 | WORKDIR / 5 | CMD ["/bin/bash"] -------------------- ERROR: failed to solve: source can't be a URL for COPY ``` :::info **COPY** naredba ne dopušta kopiranje dokumenata s udaljenih lokacija putem URL-a. Potrebno je koristiti **ADD** naredbu. ::: ```dockerfile FROM ubuntu:latest ENV WEBSITE1=https://i.ebayimg.com/images/g/c-IAAOSwyNVgeYQa/s-l1600.jpg ADD $WEBSITE1 / WORKDIR / CMD ["/bin/bash"] ``` ```shell $ docker run -it --rm primjer2:02 root@000ae4df8c22:/# ``` - za razliku od priješnjih naredbi koristimo `--rm` kako bi se kontejner po završetku izbrisao. - sada kada je slika kopirana u kontejer instalirati ćemo program kojim bi je pregledali. Kako radimo u **CLI** pokušati ćemo sliku pretvoriti u **ASCII** kod. #### Korak 2: dodavanje paketa na osnovni image ```dockerfile FROM ubuntu:latest RUN apt-get install -y jp2a ENV WEBSITE1=https://i.ebayimg.com/images/g/c-IAAOSwyNVgeYQa/s-l1600.jpg ADD $WEBSITE1 / WORKDIR / CMD ["/bin/bash"] ``` ```shell! $ docker build -t primjer2:03 . [+] Building 0.4s (6/7) docker:default => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 207B 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [internal] load metadata for docker.io/ ... 0.0s => CACHED [1/4] FROM docker.io/library/ubuntu:latest 0.0s => CANCELED https://i.ebayimg.com/images/g/c-I... 0.3s => ERROR [2/4] RUN apt-get install -y jp2a 0.3s ------ > [2/4] RUN apt-get install -y jp2a: 0.300 Reading package lists... 0.308 Building dependency tree... 0.309 Reading state information... 0.310 E: Unable to locate package jp2a ------ Dockerfile:2 -------------------- 1 | FROM ubuntu:latest 2 | >>> RUN apt-get install -y jp2a 3 | ENV WEBSITE1=https://i.ebayimg.com/images/g/c-IAAOSwyNVgeYQa/s-l1600.jpg 4 | ADD $WEBSITE1 / -------------------- ERROR: failed to solve: process "/bin/sh -c apt-get install -y jp2a" did not complete successfully: exit code: 100 ``` :::info potrebno je prvo osvježiti ubuntu da bi mogli instalirati jp2a paket ::: ```dockerfile FROM ubuntu:latest RUN apt-get update RUN apt-get install -y jp2a ENV WEBSITE1=https://i.ebayimg.com/images/g/c-IAAOSwyNVgeYQa/s-l1600.jpg ADD $WEBSITE1 / WORKDIR / CMD ["/bin/bash"] ``` ```shell! $ docker run -it --rm primjer2:04 root@72f70a86f24f:/# jp2a s-l1600.jpg MKdxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxdKM MkKKddNMkdOMXddKMMMMMxdOMMMMMMMMMxdddxkXMMWdddddddXKkM MkKo 0M, 'MO dMMMMW ,MMMMMMMMM .. ;MW ....0KkM MkKo 0M0 XMO dMMMMW ,MMMMMMMMM 'MM, NW ;MMMMMKkM MkKo 0MWWMMO dMMMMW ,MMMMMMMMM 'WX. .WW ;MMMMMKkM MkKo 0MMMMMO dMMMMW ,MMMMMMMMM .0MW kMKkM MkKo 0MMMMMO dMMMMW ,MMMMMMMMM .XK; KW 'OOONMKkM MkKo 0MMMMMO dMMMMW ,MMMMMMMMM 'MMx xW ;MMMMMKkM MkKo 0MMMMMO :xxxOW .xxxxWMMMM .xx' KW .xxxxNKkM MkKd..KMMMMM0......,W.......NMMMM......:0MW.......0KkM Mk:cccccccccccccccccccccccccccccccccccccccccccccccc:kM Mk:cccccc;. .cccc: .:oddl, :cc' ccc.kM MkXMMMMMMMM0 kMMMMM dMMMWWMMN' XMMd 0MMx kM MkXMMx ,MMMl WMWNMM: ,MMM, oMMX XMMd 0MMd kM MkXMMx NMMo ;MMkxMMO :MMM ;MMW XMMd OMMd kM MkXMMk..:MMW. kMM:;MMW :MMM ... XMMdOMMd kM MkXMMMMMMMN' WMM WMM: :MMM XMMMMMN kM MkXMM0::oWMM: ;MMO OMMO :MMM XMMMMMMO kM MkXMMx dMMX kMMo..oMMW :MMM '00O XMMX'XMMd kM MkXMMx dMMN WMMMMMMMMM: :MMM ;MMW XMMd .WMM: kM MkXMMO,,:NMMk ;MMK''''0MMk .MMMo.'OMM0 XMMd ;MMW. kM MkXMMMMMMMNd kMMl cMMW ;XMMMMMMk. XMMd oMMN.kM Mk....... ... ... .',,. .... ....kM MkkXXXXXXXXOkkkkkkkkkkO0ldol:dKkkkkkkkkkkkKXXXXXXXXkkM MkKMMMMMMMMXxxOdxxdxko0X:doo0loO0oOxkkxoxdWMMMMMMMMKkM MkKMMMMMMMMMOKKlodkKddkdkllNxolkkdMdkkodKdWMMMMMMMMKkM MKdxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxdKM ``` #### Korak 3: prikaz dokumenta kod pokretanja kontejnera ```dockerfile FROM ubuntu:latest RUN apt-get update RUN apt-get install -y jp2a RUN apt-get install -y vim ENV WEBSITE1=https://i.ebayimg.com/images/g/c-IAAOSwyNVgeYQa/s-l1600.jpg ENV WEBSITE2=https://raw.githubusercontent.com/lhartikk/ArnoldC/master/README.md ADD $WEBSITE1 / ADD $WEBSITE2 / WORKDIR / CMD ["vim","README.md"] ``` - dodajmo još jednu ENV varijablu i prikažimo dokument kada se kontejner pokrene. :::info Obratite pažnju na redoslijed naredbi tj. slojeva. ::: ```shell! # ArnoldC Programming language based on the one-liners of Arnold Schwarzenegger. ## Motivation Although the one-liners of Arnold Schwarzenegger are fairly well known the true semantics of the uttering is yet to be understood. This project tries to discover new meanings from the Arnold movies with the means of computer science. ## HelloWorld.arnoldc IT'S SHOWTIME TALK TO THE HAND "hello world" YOU HAVE BEEN TERMINATED ... ``` - za izlazak koristite **ESC**, **q!**, **ENTER**. #### Korak 4: dodavanje korisnika ```dockerfile FROM ubuntu:latest RUN apt-get update RUN apt-get install -y jp2a RUN apt-get install -y vim RUN useradd -m arni ENV WEBSITE1=https://i.ebayimg.com/images/g/c-IAAOSwyNVgeYQa/s-l1600.jpg ENV WEBSITE2=https://raw.githubusercontent.com/lhartikk/ArnoldC/master/README.md ADD $WEBSITE1 / ADD $WEBSITE2 / WORKDIR / USER arni CMD ["vim","README.md"] ``` ```shell $ docker run -it --rm primjer2:05 ... "README.md" [Permission Denied] ``` :::info Provjerimo možemo li uz pomoć **sudo** pokrenuti dokument kroz vim. ::: ```shell $ docker run -it --rm primjer2:05 bash arni@34995e3f534a:/$ sudo vim README.md bash: sudo: command not found ``` :::info Potrebno je instalirati **sudo**. ::: ```dockerfile FROM ubuntu:latest RUN apt-get update RUN apt-get install -y jp2a RUN apt-get install -y vim RUN apt-get install -y sudo RUN useradd -m arni && echo "arni:arni" | chpasswd && adduser arni sudo ENV WEBSITE1=https://i.ebayimg.com/images/g/c-IAAOSwyNVgeYQa/s-l1600.jpg ENV WEBSITE2=https://raw.githubusercontent.com/lhartikk/ArnoldC/master/README.md ADD $WEBSITE1 / ADD $WEBSITE2 / WORKDIR / USER arni RUN sudo chmod 777 README.md CMD ["vim","README.md"] ``` ```shell $ docker build -t primjer2:06 . [+] Building 0.8s (14/14) FINISHED => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 491B 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [internal] load metadata for docker.io/library/ubuntu:latest 0.1s => [ 1/10] FROM docker.io/library/ubuntu:latest@sha256:9 ... 0.0s => https://raw.githubusercontent.com/lhartikk/ArnoldC/master/README.md 0.1s => https://i.ebayimg.com/images/g/c-IAAOSwyNVgeYQa/s-l1600.jpg 0.0s => CACHED [ 2/10] RUN apt-get update 0.0s => CACHED [ 3/10] RUN apt-get install -y jp2a 0.0s => CACHED [ 4/10] RUN apt-get install -y vim 0.0s => CACHED [ 5/10] RUN apt-get install -y sudo 0.0s => CACHED [ 6/10] RUN useradd -m arni && echo "arni:arni" | chpas ... 0.0s => CACHED [ 7/10] ADD https://i.ebayimg.com/images/g/c-IAAOSwyNVg ... 0.0s => CACHED [ 8/10] ADD https://raw.githubusercontent.com/lhartik ... 0.0s => ERROR [ 9/10] RUN sudo chmod 777 README.md 0.4s ------ > [ 9/10] RUN sudo chmod 777 README.md: #0 0.355 sudo: a terminal is required to read the password; #either use the -S option to read from standard input or #configure an askpass helper #0 0.355 sudo: a password is required ------ Dockerfile:13 -------------------- 11 | WORKDIR / 12 | USER arni 13 | >>> RUN sudo chmod 777 README.md 14 | CMD ["vim","README.md"] 15 | -------------------- ERROR: failed to solve: process "/bin/sh -c sudo chmod 777 README.md" did not complete successfully: exit code: 1 ``` :::info **sudo** zahtjeva lozinku prilikom pozivanja. Potrebno je proslijediti lozinku kao argumnet tijekom kreiranja image-a. ::: ```dockerfile FROM ubuntu:latest RUN apt-get update RUN apt-get install -y jp2a RUN apt-get install -y vim RUN apt-get install -y sudo RUN useradd -m arni && echo "arni:arni" | chpasswd && adduser arni sudo ENV WEBSITE1=https://i.ebayimg.com/images/g/c-IAAOSwyNVgeYQa/s-l1600.jpg ENV WEBSITE2=https://raw.githubusercontent.com/lhartikk/ArnoldC/master/README.md ADD $WEBSITE1 / ADD $WEBSITE2 / WORKDIR / USER arni ARG user_pass RUN echo $user_pass | sudo -S chmod 777 README.md CMD ["vim","README.md"] ``` ```shell $ docker build --build-arg user_pass=arni -t primjer2:07 . [+] Building 0.8s (15/15) FINISHED => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 526B ... ``` :::success Kontejner je uspješno pokrenut no isto je potrebno učiniti i za s-l1600.jpg dokumnet. Puno elegantnije rješenje je kopirati dokumente, promjeniti im prava te onda pozvati korisnika. Na taj način nije više potrebno dodavati korisnika u sudo grupu. ```dockerfile FROM ubuntu:latest RUN apt-get update RUN apt-get install -y jp2a RUN apt-get install -y vim RUN useradd -m arni ENV WEBSITE1=https://i.ebayimg.com/images/g/c-IAAOSwyNVgeYQa/s-l1600.jpg ENV WEBSITE2=https://raw.githubusercontent.com/lhartikk/ArnoldC/master/README.md ADD $WEBSITE1 / ADD $WEBSITE2 / WORKDIR / RUN chmod 777 /s-l1600.jpg RUN chmod 777 /README.md USER arni CMD ["vim","README.md"] ``` :::