---
# System prepended metadata

title: 'MMOS 2025/26: Vježba 05'
tags: [MMOS_2526]

---

---
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"]
```
:::