frame

Sveiki apsilankę!

Jei forume lankaisi pirmą kartą, kviečiame registruotis ir prisijungti prie diskusijų.

Prisijungti Registruotis

[KVM] Kaip nustatyti ir ištaisyti dažniausiai kylančias Docker problemas?

iv_vytenisgiv_vytenisg Super Moderator
edited rugsėjo 24 Į Tipinės problemos


Docker palengvina aplikacijų administravimą naudodamas konteinerių technologiją. Tačiau pasitaiko atveju kai tenka susidurti su problemomis integruojant papildinius, kurių reikalauja Jūsų naudojamos aplikacijos laikomos konteineriuose, ypač jeigu nesate patyręs Docker naudotojas. Dažniausiai pasitaikančios problemos yra susijusios su bibliotekomis, moduliais bei susijungimais su kitais konteineriais.


0. Preliminarūs reikalavimai

KVM Linux serveris su įdiegtu Docker. Docker diegimas gali būti atliekamas pagal šią pamoką.


1. Dockerfile problemų sprendimas

Dažniausiai susiduriama su problemomis kai kuriama Docker image. Visų pirma pateikiame skirtumą tarp image ir konteinerių:
  • Image yra resursas turintis tik nuskaitymo galimybę. Šis resursas gali būti sukuriamas naudojant Dockerfile. Tai yra resursas, kurį galite dalintis su kitais konteineriais Docker aplinkoje.
  • Konteineris tai yra įrašomas bei skaitomas resursas, kurį galite sukurti naudodami image, kurią jau sukūrėte anksčiau.

Peržiūrėjus Dockerfile galite matyti žingsnį po žingsnio visus veiksmus, kuriais buvo sukurtas image. Tai reiškia, kad jeigu matote aiškius įvykdytus žingsnius, visi anksčiau buvę žingsniai yra sėkmingai įvykdyti.

Pasibandymui galime sukurti nedidelį image tam, kad susipažintume su Dockerfile. Sukurkite docker_image direktorijoje, kurį būtų pagrindinėje direktorijoje ir naudodami Nano teksto redagavimo įrankį sukurti Dockerfile:
mkdir ~/docker_image
nano ~/docker_image/Dockerfile

Ir įkelkite žemiau pateiktą tekstą:
# base image
FROM debian:latest

# install basic apps
RUN aapt-get install -qy nano

Toliau galite sukurti image iš šio failo tam, kad pamatytumėte, kaip Docker apdoroja nekorektišką komandą. Sukurti image naudodami šį kodą:
docker build -t my_image ~/docker_image

Ir pamatysite šį pranešimą terminale:
Step 2 : RUN aapt-get install -qy nano
  ---> Running in 085fa10ffcc2
/bin/sh: 1: aapt-get: not found
The command '/bin/sh -c aapt-get install -qy nano' returned a non-zero code: 127

Pranešimas nurodo, kad problema yra antrame žingsnyje. Šį kartą mes naudojome aapt-get vietoje apt-get. Bet tai taip pat reiškia, kad ankstesnis žingsnis buvo įvykdytas korektiškai.

Toliau koreguosime Dockerfile ir pašalinsime klaidingą komandą:
# install basic apps
RUN apt-get install -qy nano

Paleiskite docker build komandą pakartotinai:
docker build -t my_image ~/docker_image

Ir pamatysite pateikiamą tekstą:
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM debian:latest
---> ddf73f48a05d
Step 2 : RUN apt-get install -qy nano
---> Running in 9679323b942f
Reading package lists...
Building dependency tree...
E: Unable to locate package nano
The command '/bin/sh -c apt-get install -qy nano' returned a non-zero code: 100

Su korekcijomis procesas buvo atlikti truputi greičiau, nes Docker buvo išsisaugojęs pirmą žingsnį ir nebesiuntė iš naujo bazinės image. Tačiau yra gaunamas naujas klaidos kodas. Norint jį ištaisyti reikia modifikuoti Dockerfile ir atlikti išvalymą bei gražinti į pradžios stadiją. Atsidarykite konfigūracinį failą:
nano ~/docker_image/Dockerfile

Pridėti paryškintą eilutę aukščiau nei komanda įrašyti Nano:
# base image
FROM debian:latest

# clean and update sources
[B]RUN apt-get clean && apt-get update[/B]

# install basic apps
RUN apt-get install -qy nano

Išsaugokite failą ir paleiskite docker build dar kartą:
docker build -t my_image ~/docker_image

Šį kartą procesas bus įvykdytas sėkmingai:
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM debian:latest
 ---> a24c3183e910
Step 2 : RUN apt-get install -qy nano
 ---> Running in 2237d254f172
Reading package lists...
Building dependency tree...
Reading state information...
Suggested packages:
  spell
The following NEW packages will be installed:
  nano
...

 ---> 64ff1d3d71d6
Removing intermediate container 2237d254f172
Successfully built 64ff1d3d71d6

Patikrinkime, kas atsitiks kai pridėsime Python 3 ir PostgreSQL driver'ius į image. Atidarykite Dockerfile dar kartą:
nano ~/docker_image/Dockerfile

Ir pridėkite paryškintas eilutes:
# base image
FROM debian:latest

# clean and update sources
RUN apt-get clean && apt-get update

# install basic apps
RUN apt-get install -qy nano

# install Python and modules
[B]RUN apt-get install -qy python3
RUN apt-get install -qy python3-psycopg2[/B]

Išsaugokite failą, išeikite iš jo ir sukurkite image dar kartą:
docker build -t my_image ~/docker_image

Kaip pastebite iš pateikiamo atsakymo, paketai buvo įdiegti sėkmingai. Procesai yra įvykdomi greičiau, nes buvo procesai buvo išsaugoti laikinojo atmintyje. Pateikiamas atsakymas:
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM debian:latest
 ---> ddf73f48a05d
Step 2 : RUN apt-get clean && apt-get update
 ---> Using cache
 ---> 2c5013476fbf
Step 3 : RUN apt-get install -qy nano
 ---> Using cache
 ---> 4b77ac535cca
Step 4 : RUN apt-get install -qy python3
 ---> Running in 93f2d795fefc
Reading package lists...
Building dependency tree...
Reading state information...
The following extra packages will be installed:
  krb5-locales libgmp10 libgnutls-deb0-28 libgssapi-krb5-2 libhogweed2
  libk5crypto3 libkeyutils1 libkrb5-3 libkrb5support0 libldap-2.4-2 libnettle4
  libp11-kit0 libpq5 libsasl2-2 libsasl2-modules libsasl2-modules-db
  libtasn1-6
Suggested packages:
  gnutls-bin krb5-doc krb5-user libsasl2-modules-otp libsasl2-modules-ldap
  libsasl2-modules-sql libsasl2-modules-gssapi-mit
  libsasl2-modules-gssapi-heimdal python-psycopg2-doc
The following NEW packages will be installed:
  krb5-locales libgmp10 libgnutls-deb0-28 libgssapi-krb5-2 libhogweed2
  libk5crypto3 libkeyutils1 libkrb5-3 libkrb5support0 libldap-2.4-2 libnettle4
  libp11-kit0 libpq5 libsasl2-2 libsasl2-modules libsasl2-modules-db
  libtasn1-6 python3-psycopg2
0 upgraded, 18 newly installed, 0 to remove and 0 not upgraded.
Need to get 5416 kB of archives.
After this operation, 10.4 MB of additional disk space will be used.

...

Processing triggers for libc-bin (2.19-18+deb8u6) ...
 ---> 978e0fa7afa7
Removing intermediate container d7d4376c9f0d
Successfully built 978e0fa7afa7

Visada rekomenduojame įdėmiai peržiūrėti pateikiamus atsakymus komandinėje eilutėje. Paleiskite atnaujinimus build time aplinkoje būdami konteineryje tam, kad nebūtumėte sustabdyti laikinojoje atmintyje esančiu paketų sąrašu.


2. Konteinerių pavadinimų problemos:

Kuo daugiau konteinerių turėsite, tuo daugiau šansų, kad susidursite su konteinerių pavadinimų problemomis - kai kurie konteineriai turės tokius pačius pavadinimus. Panagrinėkime kaip pervadinti ar pašalinti konteinerius tam, kad išvengti užvardinimo problemų.

Paleiskite konteinerį iš anksčiau naudoto image. Įvykdykite šią komandą:
docker run -ti my_image bash

Kai konteineris startuos pamatysite, kad naudojatės pagrindiniu konteinerio naudotoju:
root@80a0ca58s6ec:/#

Kai jau turite veikiantį konteinerį peržvelkime su kokiomis problemomis yra galimybė susidurti.

Kai paleidžiate konteinerį be konkretaus pavadinimo, kaip padarėme dabar, Docker atsitiktinai parenka konteineriui pavadinimą. Galite matyti visus veikiančius konteinerius paleisdami komandą docker ps atsijungę iš konteinerio. Atsijunkite iš konteinerio ir įvykdykite komandą:
docker ps

Ši komanda pateiks veikiančių konteinerių sąrašą, kaip pavyzdžiui:
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
80a0ca58d6ec        my_image            "bash"              22 seconds ago      Up 28 seconds                           docker_container

Jums bus pateikiamas kitoks pavadinimas nei docker_container. Docker automatiškai parenka pavadinimą ir tai gali sukelti problemų norint nustatyti, koks tai konteineris.

Norint nustatyti konkretų konteinerį galime naudoti - -name argumentą paleidžiant konteinerį. Arba galime pervadinti konteinerį į konkretesnį pavadinimą. Paleiskite komandą:
docker rename jūsų_konteinerio_pavadinimas python_box

Tada peržiūrėkite konteinerių sąrašą:
docker ps

Pateikiamame atsakyme matysite, kad sėkmingai pervadinimo konteinerį:
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
80a0ca58d6ec        my_image            "bash"              24 minutes ago      Up 24 minutes                           python_box

Norint uždaryti konteinerį įveskite exit būdami konteinerio direktorijoje:
root@80a0ca58d6ec:/# exit

Taip pat, galite išjungti konteinerį jame nebūdami:
docker kill python_box

Kai išjungsite konteinerį tokiu būdu, Docker pateiks atsakymą koks konteineris buvo išjungtas:
python_box

Tam, kad įsitikintumėte, kad konteineris neegzistuoja, paleiskite komandą:
docker ps

Gausite atsakymą:
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

Šiuo atveju panašu, kad galima būtų sukurti kitą konteinerį su tokiu pačiu pavadinimu, tačiau patikrinkime ar pavyks. Naudosime - -name argumentą nustatant konteinerio pavadinimą:
docker run --name python_box -ti my_image bash

Pateikiamas atsakymas:
docker: Error response from daemon: Conflict. The name "/python_box" is already in use by container 80a0ca58d6ecc80b305463aff2a68c4cbe36f7bda15e680651830fc5f9dda772. You have to remove (or rename) that container to be able to reuse that name..
See 'docker run --help'.

Jūs negalite perrašyti konteinerio pavadinimo (image pavadinimą galima pervadinti), kuris jau egzistuoja. Docker rašo, kad toks konteineris egzistuoja nepaisant to, kad mes jį pašalinome. Jis nėra veikiantis, tačiau vis dar išlieka galimybė jį startuotį. Mes jį sustabdėme, bet nepašalinome. Komanda docker ps rodo tik veikiančius konteinerius, todėl nėra matomas sustabdytas konteineris.

Tam, kad paleistume visus konteinerius yra naudojama komanda:
docker ps -a

Dabar konteineris python_box bus matomas sąraše:
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                        PORTS               NAMES
80a0ca58d6ec        my_image            "bash"              12 minutes ago      Exited (137) 6 minutes ago                       python_box

Konteinerio statusas yra Exited (137), todėl mes ir susidūrėme su pervadinimo problema kai bandėme sukurti konteinerį tuo pačiu pavadinimu.

Norint pilnai pašalinti konteinerį yra naudojama komanda:
docker rm python_box

Ir Docker pateikia konteinerio pavadinimą, kurį pašalino:
python_box

Toliau sukurkime naują serverį su pavadinimu python_box, kurį pašalinome anksčiau:
docker run --name python_box -ti my_image bash

Procesas sėkmingai įvykdomas ir automatiškai prijungiame prie konteinerio root direktorijos:
root@c05ac9d0c010:/#

Atlikus testavimus reikėtų pašalinti šį konteinerį tam, kad nekiltų problemų ateityje. Išėję iš konteinerio atlikite komandą:
docker kill python_box && docker rm python_box

Mes sujungėme dvi komandas į vieną, todėl bus pateikiamas konteinerio pavadinimas du kartus. Pirmas nurodys, kad išjungėme konteinerį, o antras, kad pašalinome:
python_box
python_box

Naudokite docker ps -a norėdami patikrinti ar konteineris yra tikrai pašalintas ir galima naudoti jo pavadinimą naujo konteinerio sukūrimui.


3. Susijungimų tarp konteinerių problemų sprendimas

Kadangi konteineriai atskiria skirtingas aplikacijas ir leidžia lengviau jam modifikuoti, pasitaiko atveju kai vienas iš konteinerių būna sugadinamas. Tada tenka jį pakeisti nauju, kas dažnai iššaukia susijungimo problemas.

Testavimui atlikti susikursime du skirtingus konteinerius - Python ir PostgreSQL. Visų pirma sukursime konteinerį su PostgreSQL duomenų baze. Konteinerio užvadinimui naudosime - -name argumentą. Pavadinimas bus postgre_box:
docker run --name postgres_box --detach postgres

Kaip pastebėjote, naudojamas ir - -detach argumentas, kuris leidžia paleisti konteinerį ir automatiškai neprijungia prie jo. Taip pat naudojamas postgres argumentas leidžiantis paleisti PostgreSQL duomenų bazę konteinerio viduje. Atlikus aukščiau pateiktą komandą gausite atsakymą, kuriame matysite konteinerio pilną ID:
Unable to find image 'postgres:latest' locally
latest: Pulling from library/postgres
6a5a5368e0c2: Already exists
193f770cec44: Pull complete
...
484ac0d6f901: Pull complete
Digest: sha256:924650288891ce2e603c4bbe8491e7fa28d43a3fc792e302222a938ff4e6a349
Status: Downloaded newer image for postgres:latest
[B]f6609b9e96cc874be0852e400381db76a19ebfa4bd94fe326477b70b8f0aff65[/B]

Atsidarykite konteinerių sąrašą tam, kad matytumėte ar konteineris veikia:
docker ps

Pateikiamas atsakymas, kuris nurodo, kad postgres_box veikia naudojant 5432 prievadą:
CONTAINER ID        IMAGE               COMMAND                  CREATED                  STATUS              PORTS               NAMES
7a230b56cd64        postgres_box            "/docker-entrypoint.s"   Less than a second ago   Up 2 seconds        5432/tcp            postgres

Dabar laikas paleisti Python konteinerį. Tam, kad jis matytų postgres_box konteinerį reikia nurodyti kito konteinerio vietą naudojant - -link argumentą. Python konteinerio paleidimui naudojama komanda:
docker run --name python_box --link postgres_box:postgres -ti my_image bash

Dabar atliksime PostgreSQL konteinerio sujungimą su python_box konteineriu:
root@3053f74c8c13:/# nano pg_test.by

Ir pridėkite žemiau pateiktą tekstą:
"""Test PostgreSQL connection."""
import psycopg2

conn = psycopg2.connect(user='postgres')
print(conn)

Dabar galime sužinoti, kas atsitiks kai bandysite kreiptis į kitą konteinerį:
root@3053f74c8c13:/# python3 pg_test.py

Ir Jums bus patiekiamas atsakymas:
Traceback (most recent call last):
  File "pg_test.py", line 5, in <module>
    conn = psycopg2.connect(database="test", user="postgres", password="secret")
  File "/usr/lib/python3/dist-packages/psycopg2/__init__.py", line 164, in connect
    conn = _connect(dsn, connection_factory=connection_factory, async=async)
psycopg2.OperationalError: could not connect to server: No such file or directory
    Is the server running locally and accepting
    connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?

Kaip matote, nepavyksta susijungti su duomenų baze, nes Python bando susijungti su duomenų baze lokaliai, o tai nepavyks padaryti, nes duomenų bazė yra kitame konteineryje. Tai tas pats, kad bandytumėte susijungti lokaliai su kitame serveryje esančia duomenų baze.

Susijungimą galite įvykdyti naudojant konteinerio pavadinimą ir peržiūrint etc/hosts failą ptyhon_box konteineryje:
root@3053f74c8c13:/# cat /etc/hosts

Pamatysite, kad postgres yra tikrai pasiekiamas:
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2      postgres f6609b9e96cc postgres_box
172.17.0.3      3053f74c8c13

Todėl dabar galime modifikuoti Python skriptą ir pridėti serverio pavadinimą. Atsidarykite failą:
root@3053f74c8c13:/# nano pg_test.py

Ir nurodykite serverio pavadinimą taip, kaip pavyzdyje:
"""Test PostgreSQL connection."""
import psycopg2

conn = psycopg2.connect(host='postgres', user='postgres')
print(conn)

Išsaugokite tekstą ir paleiskite skriptą iš naujo:
root@3053f74c8c13:/# python3 pg_test.py

Šį kartą skriptas suveiks sėkmingai be problemų:
<connection object at 0x7f64caec69d8; dsn: 'user=postgres host=7a230b56cd64', closed: 0>

Visada stenkitės naudoti konteinerių vardus tam, kad sėkmingai įvykdytumėte susijungimus.

4. Apibendrinimas

Katik apžvelgėme pagrindines problemas su kuriomis tenka susidurti administruojant Docker. Docker taip pat turi - -debug argumentą, kuris naudojamas Docker kūrėjų. Tačiau jeigu norite sužinoti daugiau apie Docker problemas, naudokite šią komandą:
docker -D [command] [arguments]

Taip pat rekomenduojame susipažinti su pagrindinėmis taisyklėmis bei eko sistema ir manome, kad dauguma konceptų, kurie iš pradžių atrodė nežinomi, turėtų tapti aiškesni.
Pažymėtos temos:
Norėdami palikti komentarą, turite prisijungti arba registruokis.