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
RUN apt-get clean && apt-get update
# 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
RUN apt-get install -qy python3
RUN apt-get install -qy python3-psycopg2
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
f6609b9e96cc874be0852e400381db76a19ebfa4bd94fe326477b70b8f0aff65
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.