Докер ва ҳама, ҳама, ҳама

TL; DR: Мақолаи мухтасар - дастур оид ба муқоисаи муҳитҳо барои иҷрои барномаҳо дар контейнерҳо. Имкониятҳои Docker ва дигар системаҳои шабеҳ баррасӣ карда мешаванд.

Докер ва ҳама, ҳама, ҳама

Таърихи каме дар бораи он ки ҳама аз куҷо пайдо шудааст

ҳикояи

Аввалин роҳи маъруфи ҷудо кардани барнома chroot мебошад. Даъвати системавӣ бо ҳамон ном тағиротро ба директорияи реша таъмин мекунад - ҳамин тавр дастрасӣ ба барномае, ки онро даъват кардааст, дастрасиро танҳо ба файлҳои дохили ин директория таъмин мекунад. Аммо агар ба барнома дар дохили он ҳуқуқҳои суперкорбарӣ дода шавад, он метавонад эҳтимолан аз chroot "гурехтан" шавад ва ба системаи асосии оператсионӣ дастрасӣ пайдо кунад. Ғайр аз он, ба ғайр аз тағир додани феҳристи реша, захираҳои дигар (RAM, протсессор), инчунин дастрасӣ ба шабака маҳдуд нестанд.

Роҳи дигар ин ба кор андохтани системаи оператсионии мукаммал дар дохили контейнер бо истифода аз механизмҳои ядрои системаи оператсионӣ мебошад. Ин усулро дар системаҳои оператсионии гуногун ба таври гуногун меноманд, аммо моҳият як аст - кор кардани якчанд системаи оператсионии мустақил, ки ҳар яки онҳо дар як ядрое, ки системаи оператсионии асосиро идора мекунад, кор мекунад. Ба ин зиндонҳои FreeBSD, Solaris Zones, OpenVZ ва LXC барои Linux дохил мешаванд. Изолятсия на танҳо барои фазои диск, балки барои дигар захираҳо пешбинӣ шудааст, аз ҷумла, ҳар як контейнер метавонад дар вақти протсессор, RAM, фарохмаҷрои шабака маҳдудият дошта бошад. Дар муқоиса бо chroot, тарк кардани контейнер мушкилтар аст, зеро суперистифодабарандаи контейнер танҳо ба дохили контейнер дастрасӣ дорад, аммо аз сабаби зарурати нигоҳ доштани системаи амалиётии дохили контейнер ва истифодаи ядрои кӯҳна версияҳои (барои Linux, ба андозаи камтар FreeBSD мувофиқ аст), эҳтимолияти шикастани системаи изолятсияи ядро ​​​​ва дастрасӣ ба системаи асосии амалиётӣ ба сифр баробар нест.

Ба ҷои ба кор андохтани системаи оператсионии мукаммал дар контейнер (бо системаи ибтидоӣ, мудири баста ва ғайра) барномаҳоро фавран оғоз кардан мумкин аст, чизи асосӣ ин аст, ки барномаҳо бо ин имконият (мавҷудияти китобхонаҳои зарурӣ ва файлҳои дигар). Ин идея ҳамчун асос барои виртуализатсияи барномаҳои контейнерӣ хидмат кард, ки намояндаи барҷастатарин ва маъруфи он Docker мебошад. Дар муқоиса бо системаҳои қаблӣ, механизмҳои изолятсияи фасењтар, дар якҷоягӣ бо дастгирии дарунсохт барои шабакаҳои виртуалӣ байни контейнерҳо ва ҳолати барнома дар дохили контейнер, ба қобилияти сохтани муҳити ягонаи ягона аз шумораи зиёди серверҳои физикӣ барои идора кардани контейнерҳо оварда расонд - бе зарурати идоракунии захираҳои дастӣ.

Доктор

Docker маъруфтарин нармафзори контейнерсозии барномаҳо мебошад. Он бо забони Go навишта шудааст, ки имкониятҳои муқаррарии ядрои Linux - гурӯҳҳо, фазоҳои номҳо, қобилиятҳо ва ғайра, инчунин системаҳои файлии Aufs ва дигарҳоро барои сарфаи фазои диск истифода мебарад.

Докер ва ҳама, ҳама, ҳама
Манбаъ: wikimedia

меъморӣ

Пеш аз версияи 1.11, Docker ҳамчун хидмати ягона кор мекард, ки ҳама амалиётҳоро бо контейнерҳо иҷро мекард: зеркашии тасвирҳо барои контейнерҳо, кушодани контейнерҳо, коркарди дархостҳои API. Аз версияи 1.11, Docker ба якчанд қисмҳо тақсим шудааст, ки бо ҳамдигар ҳамкорӣ мекунанд: контейнер, барои коркарди тамоми давраи ҳаёти контейнерҳо (тақсимоти фазои диск, зеркашии тасвирҳо, шабака, оғоз, насб ва мониторинги ҳолати контейнерҳо) ва runC , вақтҳои кори контейнер, ки дар асоси истифодаи гурӯҳҳо ва дигар хусусиятҳои ядрои Linux. Худи хидмати докер боқӣ мемонад, аммо ҳоло он танҳо барои коркарди дархостҳои API, ки ба контейнер пахш мешавад, хидмат мекунад.

Докер ва ҳама, ҳама, ҳама

Насб ва танзимот

Роҳи дӯстдоштаи ман барои насб кардани docker docker-machine мебошад, ки ба ғайр аз мустақиман насб кардан ва танзим кардани докер дар серверҳои дурдаст (аз ҷумла абрҳои гуногун) ба шумо имкон медиҳад, ки бо системаҳои файлии серверҳои дурдаст кор кунед ва инчунин метавонад фармонҳои гуногунро иҷро кунед.

Аммо, аз соли 2018 инҷониб лоиҳа базӯр таҳия карда нашудааст, аз ин рӯ мо онро бо роҳи муқаррарии аксари дистрибюторҳои Linux насб мекунем - бо илова кардани анбор ва насб кардани бастаҳои зарурӣ.

Ин усул инчунин барои насби автоматӣ истифода мешавад, масалан, бо истифода аз Ansible ё дигар системаҳои шабеҳ, аммо ман онро дар ин мақола баррасӣ намекунам.

Насбкунӣ дар Centos 7 анҷом дода мешавад, ман як мошини виртуалиро ҳамчун сервер истифода мекунам, барои насб кардан танҳо фармонҳои зерро иҷро кунед:

# yum install -y yum-utils
# yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# yum install docker-ce docker-ce-cli containerd.io

Пас аз насб, шумо бояд хидматро оғоз кунед, онро ба худкор бор кунед:

# systemctl enable docker
# systemctl start docker
# firewall-cmd --zone=public --add-port=2377/tcp --permanent

Илова бар ин, шумо метавонед як гурӯҳи докер эҷод кунед, ки корбарони онҳо метавонанд бо докер бидуни sudo кор кунанд, сабти номро танзим кунанд, дастрасӣ ба APIро аз берун фаъол созанд, танзим кардани брандмауэрро фаромӯш накунед (ҳар чизе ки иҷозат дода намешавад дар мисолҳои дар боло ва дар поён овардашуда манъ аст - Ман инро барои содда ва визуализатсия сарфи назар кардам), аммо ман дар ин ҷо тафсилоти бештар нахоҳам дод.

Дигар хусусиятҳо

Илова ба мошини дар боло зикршуда, инчунин реестри докер мавҷуд аст, асбоб барои нигоҳ доштани тасвирҳо барои контейнерҳо, инчунин docker compose - асбоб барои автоматикунонии ҷойгиркунии замимаҳо дар контейнерҳо, файлҳои YAML барои сохтан ва танзим кардани контейнерҳо истифода мешаванд ва дигар чизҳои алоқаманд (масалан, шабакаҳо, системаҳои файлии доимӣ барои нигоҳ доштани маълумот).

Он инчунин метавонад барои ташкили қубурҳо барои CICD истифода шавад. Хусусияти дигари ҷолиб ин кор дар реҷаи кластерӣ мебошад, ки ба истилоҳ режими тӯда (пеш аз версияи 1.12 он ҳамчун тӯдаи докер маълум буд), ки ба шумо имкон медиҳад инфрасохтори ягонаро аз якчанд серверҳо барои идора кардани контейнерҳо ҷамъ кунед. Дар болои ҳама серверҳо дастгирии шабакаи виртуалӣ мавҷуд аст, мувозинати дарунсохташуда ва инчунин дастгирии асрор барои контейнерҳо мавҷуд аст.

Файлҳои YAML аз docker compose метавонанд барои чунин кластерҳо бо тағироти ночиз истифода шаванд, ки нигоҳдории кластерҳои хурд ва миёнаро барои мақсадҳои гуногун пурра автоматӣ мекунанд. Барои кластерҳои калон, Kubernetes афзалтар аст, зеро хароҷоти нигоҳдории режими тӯда метавонад аз ҳисоби Kubernetes зиёдтар бошад. Илова ба runC, ҳамчун муҳити иҷро барои контейнерҳо, шумо метавонед, масалан, насб кунед Контейнерҳои Ката

Кор бо Docker

Пас аз насб ва конфигуратсия, мо кӯшиш мекунем, ки кластер созем, ки дар он мо GitLab ва Реестри Docker-ро барои дастаи таҳиякунанда ҷойгир кунем. Ҳамчун серверҳо ман се мошини маҷозӣ истифода хоҳам кард, ки дар онҳо ман ба таври иловагӣ FS-и тақсимшудаи GlusterFS -ро ҷойгир мекунам ва онро ҳамчун анбори ҳаҷмҳои докер истифода хоҳам кард, масалан, барои иҷро кардани версияи аз хатогии реестри докер. Ҷузъҳои калидии иҷрошаванда: Registry Docker, Postgresql, Redis, GitLab бо дастгирии GitLab Runner дар болои Swarm. Postgresql бо кластерсозӣ оғоз карда мешавад Столон, бинобар ин ба шумо лозим нест, ки GlusterFS-ро барои нигоҳ доштани маълумоти Postgresql истифода баред. Қисми боқимондаи маълумоти муҳим дар GlusterFS нигоҳ дошта мешавад.

Барои ҷойгиркунии GlusterFS дар ҳама серверҳо (онҳо node1, node2, node3 номида мешаванд), шумо бояд бастаҳоро насб кунед, брандмауэрро фаъол созед, директорияҳои заруриро эҷод кунед:

# yum -y install centos-release-gluster7
# yum -y install glusterfs-server
# systemctl enable glusterd
# systemctl start glusterd
# firewall-cmd --add-service=glusterfs --permanent
# firewall-cmd --reload
# mkdir -p /srv/gluster
# mkdir -p /srv/docker
# echo "$(hostname):/docker /srv/docker glusterfs defaults,_netdev 0 0" >> /etc/fstab

Пас аз насб, кор оид ба конфигуратсияи GlusterFS бояд аз як гиреҳ идома дода шавад, масалан node1:

# gluster peer probe node2
# gluster peer probe node3
# gluster volume create docker replica 3 node1:/srv/gluster node2:/srv/gluster node3:/srv/gluster force
# gluster volume start docker

Пас шумо бояд ҳаҷми ҳосилшударо насб кунед (фармон бояд дар ҳама серверҳо иҷро карда шавад):

# mount /srv/docker

Ҳолати тӯда дар яке аз серверҳо танзим шудааст, ки пешво хоҳад буд, боқимондаҳо бояд ба кластер ҳамроҳ шаванд, аз ин рӯ натиҷаи иҷро кардани фармон дар сервери аввал бояд дар боқимонда нусхабардорӣ ва иҷро карда шавад.

Танзимоти ибтидоии кластер, ман фармонро дар node1 иҷро мекунам:

# docker swarm init
Swarm initialized: current node (a5jpfrh5uvo7svzz1ajduokyq) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-0c5mf7mvzc7o7vjk0wngno2dy70xs95tovfxbv4tqt9280toku-863hyosdlzvd76trfptd4xnzd xx.xx.xx.xx:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
# docker swarm join-token manager

Натиҷаи фармони дуюмро нусхабардорӣ кунед, дар node2 ва node3 иҷро кунед:

# docker swarm join --token SWMTKN-x-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxx xx.xx.xx.xx:2377
This node joined a swarm as a manager.

Ин конфигуратсияи пешакии серверҳоро ба анҷом мерасонад, биёед ба танзимоти хидматҳо шурӯъ кунем, фармонҳои иҷрошаванда аз node1 оғоз карда мешаванд, агар тартиби дигаре пешбинӣ нашуда бошад.

Пеш аз ҳама, биёед шабакаҳоро барои контейнерҳо созем:

# docker network create --driver=overlay etcd
# docker network create --driver=overlay pgsql
# docker network create --driver=overlay redis
# docker network create --driver=overlay traefik
# docker network create --driver=overlay gitlab

Сипас мо серверҳоро қайд мекунем, ин барои пайваст кардани баъзе хидматҳо ба серверҳо зарур аст:

# docker node update --label-add nodename=node1 node1
# docker node update --label-add nodename=node2 node2
# docker node update --label-add nodename=node3 node3

Минбаъд, мо директорияҳоро барои нигоҳ доштани маълумотҳои ғайра, анбори КВ, ки Traefik ва Stolon лозиманд, эҷод мекунем. Ба монанди Postgresql, инҳо контейнерҳои ба серверҳо пайвастшуда хоҳанд буд, аз ин рӯ мо ин фармонро дар ҳама серверҳо иҷро мекунем:

# mkdir -p /srv/etcd

Баъдан, файлеро барои танзим кардани etcd эҷод кунед ва онро татбиқ кунед:

00etcd.yml

version: '3.7'

services:
  etcd1:
    image: quay.io/coreos/etcd:latest
    hostname: etcd1
    command:
      - etcd
      - --name=etcd1
      - --data-dir=/data.etcd
      - --advertise-client-urls=http://etcd1:2379
      - --listen-client-urls=http://0.0.0.0:2379
      - --initial-advertise-peer-urls=http://etcd1:2380
      - --listen-peer-urls=http://0.0.0.0:2380
      - --initial-cluster=etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380
      - --initial-cluster-state=new
      - --initial-cluster-token=etcd-cluster
    networks:
      - etcd
    volumes:
      - etcd1vol:/data.etcd
    deploy:
      replicas: 1
      placement:
        constraints: [node.labels.nodename == node1]
  etcd2:
    image: quay.io/coreos/etcd:latest
    hostname: etcd2
    command:
      - etcd
      - --name=etcd2
      - --data-dir=/data.etcd
      - --advertise-client-urls=http://etcd2:2379
      - --listen-client-urls=http://0.0.0.0:2379
      - --initial-advertise-peer-urls=http://etcd2:2380
      - --listen-peer-urls=http://0.0.0.0:2380
      - --initial-cluster=etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380
      - --initial-cluster-state=new
      - --initial-cluster-token=etcd-cluster
    networks:
      - etcd
    volumes:
      - etcd2vol:/data.etcd
    deploy:
      replicas: 1
      placement:
        constraints: [node.labels.nodename == node2]
  etcd3:
    image: quay.io/coreos/etcd:latest
    hostname: etcd3
    command:
      - etcd
      - --name=etcd3
      - --data-dir=/data.etcd
      - --advertise-client-urls=http://etcd3:2379
      - --listen-client-urls=http://0.0.0.0:2379
      - --initial-advertise-peer-urls=http://etcd3:2380
      - --listen-peer-urls=http://0.0.0.0:2380
      - --initial-cluster=etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380
      - --initial-cluster-state=new
      - --initial-cluster-token=etcd-cluster
    networks:
      - etcd
    volumes:
      - etcd3vol:/data.etcd
    deploy:
      replicas: 1
      placement:
        constraints: [node.labels.nodename == node3]

volumes:
  etcd1vol:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/etcd"
  etcd2vol:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/etcd"
  etcd3vol:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/etcd"

networks:
  etcd:
    external: true

# docker stack deploy --compose-file 00etcd.yml etcd

Пас аз чанде, мо тафтиш мекунем, ки кластери etcd боло рафтааст:

# docker exec $(docker ps | awk '/etcd/ {print $1}')  etcdctl member list
ade526d28b1f92f7: name=etcd1 peerURLs=http://etcd1:2380 clientURLs=http://etcd1:2379 isLeader=false
bd388e7810915853: name=etcd3 peerURLs=http://etcd3:2380 clientURLs=http://etcd3:2379 isLeader=false
d282ac2ce600c1ce: name=etcd2 peerURLs=http://etcd2:2380 clientURLs=http://etcd2:2379 isLeader=true
# docker exec $(docker ps | awk '/etcd/ {print $1}')  etcdctl cluster-health
member ade526d28b1f92f7 is healthy: got healthy result from http://etcd1:2379
member bd388e7810915853 is healthy: got healthy result from http://etcd3:2379
member d282ac2ce600c1ce is healthy: got healthy result from http://etcd2:2379
cluster is healthy

Барои Postgresql феҳристҳо эҷод кунед, фармонро дар ҳама серверҳо иҷро кунед:

# mkdir -p /srv/pgsql

Баъдан, барои танзими Postgresql файл эҷод кунед:

01pgsql.yml

version: '3.7'

services:
  pgsentinel:
    image: sorintlab/stolon:master-pg10
    command:
      - gosu
      - stolon
      - stolon-sentinel
      - --cluster-name=stolon-cluster
      - --store-backend=etcdv3
      - --store-endpoints=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379
      - --log-level=debug
    networks:
      - etcd
      - pgsql
    deploy:
      replicas: 3
      update_config:
        parallelism: 1
        delay: 30s
        order: stop-first
        failure_action: pause
  pgkeeper1:
    image: sorintlab/stolon:master-pg10
    hostname: pgkeeper1
    command:
      - gosu
      - stolon
      - stolon-keeper
      - --pg-listen-address=pgkeeper1
      - --pg-repl-username=replica
      - --uid=pgkeeper1
      - --pg-su-username=postgres
      - --pg-su-passwordfile=/run/secrets/pgsql
      - --pg-repl-passwordfile=/run/secrets/pgsql_repl
      - --data-dir=/var/lib/postgresql/data
      - --cluster-name=stolon-cluster
      - --store-backend=etcdv3
      - --store-endpoints=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379
    networks:
      - etcd
      - pgsql
    environment:
      - PGDATA=/var/lib/postgresql/data
    volumes:
      - pgkeeper1:/var/lib/postgresql/data
    secrets:
      - pgsql
      - pgsql_repl
    deploy:
      replicas: 1
      placement:
        constraints: [node.labels.nodename == node1]
  pgkeeper2:
    image: sorintlab/stolon:master-pg10
    hostname: pgkeeper2
    command:
      - gosu
      - stolon 
      - stolon-keeper
      - --pg-listen-address=pgkeeper2
      - --pg-repl-username=replica
      - --uid=pgkeeper2
      - --pg-su-username=postgres
      - --pg-su-passwordfile=/run/secrets/pgsql
      - --pg-repl-passwordfile=/run/secrets/pgsql_repl
      - --data-dir=/var/lib/postgresql/data
      - --cluster-name=stolon-cluster
      - --store-backend=etcdv3
      - --store-endpoints=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379
    networks:
      - etcd
      - pgsql
    environment:
      - PGDATA=/var/lib/postgresql/data
    volumes:
      - pgkeeper2:/var/lib/postgresql/data
    secrets:
      - pgsql
      - pgsql_repl
    deploy:
      replicas: 1
      placement:
        constraints: [node.labels.nodename == node2]
  pgkeeper3:
    image: sorintlab/stolon:master-pg10
    hostname: pgkeeper3
    command:
      - gosu
      - stolon 
      - stolon-keeper
      - --pg-listen-address=pgkeeper3
      - --pg-repl-username=replica
      - --uid=pgkeeper3
      - --pg-su-username=postgres
      - --pg-su-passwordfile=/run/secrets/pgsql
      - --pg-repl-passwordfile=/run/secrets/pgsql_repl
      - --data-dir=/var/lib/postgresql/data
      - --cluster-name=stolon-cluster
      - --store-backend=etcdv3
      - --store-endpoints=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379
    networks:
      - etcd
      - pgsql
    environment:
      - PGDATA=/var/lib/postgresql/data
    volumes:
      - pgkeeper3:/var/lib/postgresql/data
    secrets:
      - pgsql
      - pgsql_repl
    deploy:
      replicas: 1
      placement:
        constraints: [node.labels.nodename == node3]
  postgresql:
    image: sorintlab/stolon:master-pg10
    command: gosu stolon stolon-proxy --listen-address 0.0.0.0 --cluster-name stolon-cluster --store-backend=etcdv3 --store-endpoints http://etcd1:2379,http://etcd2:2379,http://etcd3:2379
    networks:
      - etcd
      - pgsql
    deploy:
      replicas: 3
      update_config:
        parallelism: 1
        delay: 30s
        order: stop-first
        failure_action: rollback

volumes:
  pgkeeper1:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/pgsql"
  pgkeeper2:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/pgsql"
  pgkeeper3:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/pgsql"

secrets:
  pgsql:
    file: "/srv/docker/postgres"
  pgsql_repl:
    file: "/srv/docker/replica"

networks:
  etcd:
    external: true
  pgsql:
    external: true

Мо сирро тавлид мекунем, файлро татбиқ мекунем:

# </dev/urandom tr -dc 234567890qwertyuopasdfghjkzxcvbnmQWERTYUPASDFGHKLZXCVBNM | head -c $(((RANDOM%3)+15)) > /srv/docker/replica
# </dev/urandom tr -dc 234567890qwertyuopasdfghjkzxcvbnmQWERTYUPASDFGHKLZXCVBNM | head -c $(((RANDOM%3)+15)) > /srv/docker/postgres
# docker stack deploy --compose-file 01pgsql.yml pgsql

Пас аз чанде (ба натиҷаи фармон нигаред хадамоти docker lsки ҳама хидматҳо баланд шуданд) кластери Postgresql-ро оғоз кунед:

# docker exec $(docker ps | awk '/pgkeeper/ {print $1}') stolonctl --cluster-name=stolon-cluster --store-backend=etcdv3 --store-endpoints=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379 init

Санҷиши омодагии кластери Postgresql:

# docker exec $(docker ps | awk '/pgkeeper/ {print $1}') stolonctl --cluster-name=stolon-cluster --store-backend=etcdv3 --store-endpoints=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379 status
=== Active sentinels ===

ID      LEADER
26baa11d    false
74e98768    false
a8cb002b    true

=== Active proxies ===

ID
4d233826
9f562f3b
b0c79ff1

=== Keepers ===

UID     HEALTHY PG LISTENADDRESS    PG HEALTHY  PG WANTEDGENERATION PG CURRENTGENERATION
pgkeeper1   true    pgkeeper1:5432         true     2           2
pgkeeper2   true    pgkeeper2:5432          true            2                   2
pgkeeper3   true    pgkeeper3:5432          true            3                   3

=== Cluster Info ===

Master Keeper: pgkeeper3

===== Keepers/DB tree =====

pgkeeper3 (master)
├─pgkeeper2
└─pgkeeper1

Мо traefik-ро барои кушодани дастрасӣ ба контейнерҳо аз берун танзим мекунем:

03traefik.yml

version: '3.7'

services:
  traefik:
    image: traefik:latest
    command: >
      --log.level=INFO
      --providers.docker=true
      --entryPoints.web.address=:80
      --providers.providersThrottleDuration=2
      --providers.docker.watch=true
      --providers.docker.swarmMode=true
      --providers.docker.swarmModeRefreshSeconds=15s
      --providers.docker.exposedbydefault=false
      --accessLog.bufferingSize=0
      --api=true
      --api.dashboard=true
      --api.insecure=true
    networks:
      - traefik
    ports:
      - 80:80
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    deploy:
      replicas: 3
      placement:
        constraints:
          - node.role == manager
        preferences:
          - spread: node.id
      labels:
        - traefik.enable=true
        - traefik.http.routers.traefik.rule=Host(`traefik.example.com`)
        - traefik.http.services.traefik.loadbalancer.server.port=8080
        - traefik.docker.network=traefik

networks:
  traefik:
    external: true

# docker stack deploy --compose-file 03traefik.yml traefik

Мо Redis Cluster-ро оғоз мекунем, барои ин мо дар ҳама гиреҳҳо феҳристи нигоҳдорӣ эҷод мекунем:

# mkdir -p /srv/redis

05redis.yml

version: '3.7'

services:
  redis-master:
    image: 'bitnami/redis:latest'
    networks:
      - redis
    ports:
      - '6379:6379'
    environment:
      - REDIS_REPLICATION_MODE=master
      - REDIS_PASSWORD=xxxxxxxxxxx
    deploy:
      mode: global
      restart_policy:
        condition: any
    volumes:
      - 'redis:/opt/bitnami/redis/etc/'

  redis-replica:
    image: 'bitnami/redis:latest'
    networks:
      - redis
    ports:
      - '6379'
    depends_on:
      - redis-master
    environment:
      - REDIS_REPLICATION_MODE=slave
      - REDIS_MASTER_HOST=redis-master
      - REDIS_MASTER_PORT_NUMBER=6379
      - REDIS_MASTER_PASSWORD=xxxxxxxxxxx
      - REDIS_PASSWORD=xxxxxxxxxxx
    deploy:
      mode: replicated
      replicas: 3
      update_config:
        parallelism: 1
        delay: 10s
      restart_policy:
        condition: any

  redis-sentinel:
    image: 'bitnami/redis:latest'
    networks:
      - redis
    ports:
      - '16379'
    depends_on:
      - redis-master
      - redis-replica
    entrypoint: |
      bash -c 'bash -s <<EOF
      "/bin/bash" -c "cat <<EOF > /opt/bitnami/redis/etc/sentinel.conf
      port 16379
      dir /tmp
      sentinel monitor master-node redis-master 6379 2
      sentinel down-after-milliseconds master-node 5000
      sentinel parallel-syncs master-node 1
      sentinel failover-timeout master-node 5000
      sentinel auth-pass master-node xxxxxxxxxxx
      sentinel announce-ip redis-sentinel
      sentinel announce-port 16379
      EOF"
      "/bin/bash" -c "redis-sentinel /opt/bitnami/redis/etc/sentinel.conf"
      EOF'
    deploy:
      mode: global
      restart_policy:
        condition: any

volumes:
  redis:
    driver: local
    driver_opts:
      type: 'none'
      o: 'bind'
      device: "/srv/redis"

networks:
  redis:
    external: true

# docker stack deploy --compose-file 05redis.yml redis

Иловаи Феҳристи Docker:

06registry.yml

version: '3.7'

services:
  registry:
    image: registry:2.6
    networks:
      - traefik
    volumes:
      - registry_data:/var/lib/registry
    deploy:
      replicas: 1
      placement:
        constraints: [node.role == manager]
      restart_policy:
        condition: on-failure
      labels:
        - traefik.enable=true
        - traefik.http.routers.registry.rule=Host(`registry.example.com`)
        - traefik.http.services.registry.loadbalancer.server.port=5000
        - traefik.docker.network=traefik

volumes:
  registry_data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/docker/registry"

networks:
  traefik:
    external: true

# mkdir /srv/docker/registry
# docker stack deploy --compose-file 06registry.yml registry

Ва ниҳоят - GitLab:

08gitlab-runner.yml

version: '3.7'

services:
  gitlab:
    image: gitlab/gitlab-ce:latest
    networks:
      - pgsql
      - redis
      - traefik
      - gitlab
    ports:
      - 22222:22
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        postgresql['enable'] = false
        redis['enable'] = false
        gitlab_rails['registry_enabled'] = false
        gitlab_rails['db_username'] = "gitlab"
        gitlab_rails['db_password'] = "XXXXXXXXXXX"
        gitlab_rails['db_host'] = "postgresql"
        gitlab_rails['db_port'] = "5432"
        gitlab_rails['db_database'] = "gitlab"
        gitlab_rails['db_adapter'] = 'postgresql'
        gitlab_rails['db_encoding'] = 'utf8'
        gitlab_rails['redis_host'] = 'redis-master'
        gitlab_rails['redis_port'] = '6379'
        gitlab_rails['redis_password'] = 'xxxxxxxxxxx'
        gitlab_rails['smtp_enable'] = true
        gitlab_rails['smtp_address'] = "smtp.yandex.ru"
        gitlab_rails['smtp_port'] = 465
        gitlab_rails['smtp_user_name'] = "[email protected]"
        gitlab_rails['smtp_password'] = "xxxxxxxxx"
        gitlab_rails['smtp_domain'] = "example.com"
        gitlab_rails['gitlab_email_from'] = '[email protected]'
        gitlab_rails['smtp_authentication'] = "login"
        gitlab_rails['smtp_tls'] = true
        gitlab_rails['smtp_enable_starttls_auto'] = true
        gitlab_rails['smtp_openssl_verify_mode'] = 'peer'
        external_url 'http://gitlab.example.com/'
        gitlab_rails['gitlab_shell_ssh_port'] = 22222
    volumes:
      - gitlab_conf:/etc/gitlab
      - gitlab_logs:/var/log/gitlab
      - gitlab_data:/var/opt/gitlab
    deploy:
      mode: replicated
      replicas: 1
      placement:
        constraints:
        - node.role == manager
      labels:
        - traefik.enable=true
        - traefik.http.routers.gitlab.rule=Host(`gitlab.example.com`)
        - traefik.http.services.gitlab.loadbalancer.server.port=80
        - traefik.docker.network=traefik
  gitlab-runner:
    image: gitlab/gitlab-runner:latest
    networks:
      - gitlab
    volumes:
      - gitlab_runner_conf:/etc/gitlab
      - /var/run/docker.sock:/var/run/docker.sock
    deploy:
      mode: replicated
      replicas: 1
      placement:
        constraints:
        - node.role == manager

volumes:
  gitlab_conf:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/docker/gitlab/conf"
  gitlab_logs:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/docker/gitlab/logs"
  gitlab_data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/docker/gitlab/data"
  gitlab_runner_conf:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/docker/gitlab/runner"

networks:
  pgsql:
    external: true
  redis:
    external: true
  traefik:
    external: true
  gitlab:
    external: true

# mkdir -p /srv/docker/gitlab/conf
# mkdir -p /srv/docker/gitlab/logs
# mkdir -p /srv/docker/gitlab/data
# mkdir -p /srv/docker/gitlab/runner
# docker stack deploy --compose-file 08gitlab-runner.yml gitlab

Ҳолати ниҳоии кластер ва хидматҳо:

# docker service ls
ID                  NAME                   MODE                REPLICAS            IMAGE                          PORTS
lef9n3m92buq        etcd_etcd1             replicated          1/1                 quay.io/coreos/etcd:latest
ij6uyyo792x5        etcd_etcd2             replicated          1/1                 quay.io/coreos/etcd:latest
fqttqpjgp6pp        etcd_etcd3             replicated          1/1                 quay.io/coreos/etcd:latest
hq5iyga28w33        gitlab_gitlab          replicated          1/1                 gitlab/gitlab-ce:latest        *:22222->22/tcp
dt7s6vs0q4qc        gitlab_gitlab-runner   replicated          1/1                 gitlab/gitlab-runner:latest
k7uoezno0h9n        pgsql_pgkeeper1        replicated          1/1                 sorintlab/stolon:master-pg10
cnrwul4r4nse        pgsql_pgkeeper2        replicated          1/1                 sorintlab/stolon:master-pg10
frflfnpty7tr        pgsql_pgkeeper3        replicated          1/1                 sorintlab/stolon:master-pg10
x7pqqchi52kq        pgsql_pgsentinel       replicated          3/3                 sorintlab/stolon:master-pg10
mwu2wl8fti4r        pgsql_postgresql       replicated          3/3                 sorintlab/stolon:master-pg10
9hkbe2vksbzb        redis_redis-master     global              3/3                 bitnami/redis:latest           *:6379->6379/tcp
l88zn8cla7dc        redis_redis-replica    replicated          3/3                 bitnami/redis:latest           *:30003->6379/tcp
1utp309xfmsy        redis_redis-sentinel   global              3/3                 bitnami/redis:latest           *:30002->16379/tcp
oteb824ylhyp        registry_registry      replicated          1/1                 registry:2.6
qovrah8nzzu8        traefik_traefik        replicated          3/3                 traefik:latest                 *:80->80/tcp, *:443->443/tcp

Боз чиро бехтар кардан мумкин аст? Боварӣ ҳосил кунед, ки Traefik-ро барои кор бо контейнерҳои https танзим кунед, рамзгузории tls барои Postgresql ва Redis илова кунед. Аммо дар маҷмӯъ, шумо метавонед онро аллакай ба таҳиягарон ҳамчун PoC диҳед. Биёед ҳоло алтернативаҳоро ба Docker дида бароем.

Подман

Боз як муҳаррики хеле маъруф барои кор кардани контейнерҳо, ки аз рӯи қуттиҳо гурӯҳбандӣ шудаанд (подҳо, гурӯҳҳои контейнерҳои якҷоя ҷойгиршуда). Баръакси Docker, он барои идора кардани контейнерҳо ягон хидмат талаб намекунад, ҳама корҳо тавассути китобхонаи libpod анҷом дода мешаванд. Инчунин дар Go навишта шудааст, барои иҷрои контейнерҳо ба монанди runC вақти кории мувофиқи OCI лозим аст.

Докер ва ҳама, ҳама, ҳама

Кор бо Подман дар маҷмӯъ ба кори Docker шабоҳат дорад, то он даме, ки шумо ин корро карда метавонед (аз ҷониби бисёре аз онҳое, ки онро озмудаанд, аз ҷумла муаллифи ин мақола даъво доранд):

$ alias docker=podman

ва шумо метавонед корро давом диҳед. Дар маҷмӯъ, вазъият бо Подман хеле ҷолиб аст, зеро агар версияҳои аввали Kubernetes бо Docker кор мекарданд, пас аз соли 2015 пас аз стандартизатсияи ҷаҳони контейнер (OCI - Ташаббуси Open Container) ва тақсим кардани Docker ба контейнер ва runC, алтернативаи Docker барои кор дар Kubernetes таҳия карда мешавад: CRI-O. Подман дар ин замина алтернатива ба Docker аст, ки дар асоси принсипҳои Kubernetes, аз ҷумла гурӯҳбандии контейнерҳо сохта шудааст, аммо ҳадафи асосии лоиҳа ба кор андохтани контейнерҳои услуби Docker бидуни хидматҳои иловагӣ мебошад. Бо сабабҳои маълум, режими тӯда вуҷуд надорад, зеро таҳиягарон ба таври возеҳ мегӯянд, ки агар ба шумо кластер лозим бошад, Kubernetes-ро гиред.

параметр

Барои насб кардан дар Centos 7, танҳо анбори Extras -ро фаъол кунед ва ҳама чизро бо фармон насб кунед:

# yum -y install podman

Дигар хусусиятҳо

Подман метавонад воҳидҳоро барои systemd тавлид кунад ва ба ин васила мушкилоти оғоз кардани контейнерҳоро пас аз бозоғозкунии сервер ҳал кунад. Илова бар ин, systemd ҳамчун pid 1 дар контейнер дуруст кор мекунад. Барои сохтани контейнерҳо як асбоби алоҳидаи сохтмон мавҷуд аст, инчунин асбобҳои тарафи сеюм мавҷуданд - аналогҳои docker-compose, ки инчунин файлҳои конфигуратсияи бо Kubernetes мувофиқро тавлид мекунанд, аз ин рӯ гузариш аз Podman ба Kubernetes то ҳадди имкон содда аст.

Кор бо Подман

Азбаски режими тӯда вуҷуд надорад (агар кластер лозим бошад, он бояд ба Kubernetes гузарад), мо онро дар контейнерҳои алоҳида ҷамъ мекунем.

Насб кардани podman-compose:

# yum -y install python3-pip
# pip3 install podman-compose

Файли конфигуратсияи натиҷавӣ барои podman каме фарқ мекунад, зеро масалан, мо маҷбур шудем, ки қисмати алоҳидаи ҳаҷмҳоро мустақиман ба бахши хидматҳо гузаронем.

gitlab-podman.yml

version: '3.7'

services:
  gitlab:
    image: gitlab/gitlab-ce:latest
    hostname: gitlab.example.com
    restart: unless-stopped
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        gitlab_rails['gitlab_shell_ssh_port'] = 22222
    ports:
      - "80:80"
      - "22222:22"
    volumes:
      - /srv/podman/gitlab/conf:/etc/gitlab
      - /srv/podman/gitlab/data:/var/opt/gitlab
      - /srv/podman/gitlab/logs:/var/log/gitlab
    networks:
      - gitlab

  gitlab-runner:
    image: gitlab/gitlab-runner:alpine
    restart: unless-stopped
    depends_on:
      - gitlab
    volumes:
      - /srv/podman/gitlab/runner:/etc/gitlab-runner
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - gitlab

networks:
  gitlab:

# podman-compose -f gitlab-runner.yml -d up

Натиҷаи кор:

# podman ps
CONTAINER ID  IMAGE                                  COMMAND               CREATED             STATUS                 PORTS                                      NAMES
da53da946c01  docker.io/gitlab/gitlab-runner:alpine  run --user=gitlab...  About a minute ago  Up About a minute ago  0.0.0.0:22222->22/tcp, 0.0.0.0:80->80/tcp  root_gitlab-runner_1
781c0103c94a  docker.io/gitlab/gitlab-ce:latest      /assets/wrapper       About a minute ago  Up About a minute ago  0.0.0.0:22222->22/tcp, 0.0.0.0:80->80/tcp  root_gitlab_1

Биёед бубинем, ки он барои systemd ва kubernetes чӣ тавлид мекунад, барои ин ба мо лозим аст, ки ном ё идентификати подкро фаҳмем:

# podman pod ls
POD ID         NAME   STATUS    CREATED          # OF CONTAINERS   INFRA ID
71fc2b2a5c63   root   Running   11 minutes ago   3                 db40ab8bf84b

Кубернетес:

# podman generate kube 71fc2b2a5c63
# Generation of Kubernetes YAML is still under development!
#
# Save the output of this file and use kubectl create -f to import
# it into Kubernetes.
#
# Created with podman-1.6.4
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: "2020-07-29T19:22:40Z"
  labels:
    app: root
  name: root
spec:
  containers:
  - command:
    - /assets/wrapper
    env:
    - name: PATH
      value: /opt/gitlab/embedded/bin:/opt/gitlab/bin:/assets:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    - name: TERM
      value: xterm
    - name: HOSTNAME
      value: gitlab.example.com
    - name: container
      value: podman
    - name: GITLAB_OMNIBUS_CONFIG
      value: |
        gitlab_rails['gitlab_shell_ssh_port'] = 22222
    - name: LANG
      value: C.UTF-8
    image: docker.io/gitlab/gitlab-ce:latest
    name: rootgitlab1
    ports:
    - containerPort: 22
      hostPort: 22222
      protocol: TCP
    - containerPort: 80
      hostPort: 80
      protocol: TCP
    resources: {}
    securityContext:
      allowPrivilegeEscalation: true
      capabilities: {}
      privileged: false
      readOnlyRootFilesystem: false
    volumeMounts:
    - mountPath: /var/opt/gitlab
      name: srv-podman-gitlab-data
    - mountPath: /var/log/gitlab
      name: srv-podman-gitlab-logs
    - mountPath: /etc/gitlab
      name: srv-podman-gitlab-conf
    workingDir: /
  - command:
    - run
    - --user=gitlab-runner
    - --working-directory=/home/gitlab-runner
    env:
    - name: PATH
      value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    - name: TERM
      value: xterm
    - name: HOSTNAME
    - name: container
      value: podman
    image: docker.io/gitlab/gitlab-runner:alpine
    name: rootgitlab-runner1
    resources: {}
    securityContext:
      allowPrivilegeEscalation: true
      capabilities: {}
      privileged: false
      readOnlyRootFilesystem: false
    volumeMounts:
    - mountPath: /etc/gitlab-runner
      name: srv-podman-gitlab-runner
    - mountPath: /var/run/docker.sock
      name: var-run-docker.sock
    workingDir: /
  volumes:
  - hostPath:
      path: /srv/podman/gitlab/runner
      type: Directory
    name: srv-podman-gitlab-runner
  - hostPath:
      path: /var/run/docker.sock
      type: File
    name: var-run-docker.sock
  - hostPath:
      path: /srv/podman/gitlab/data
      type: Directory
    name: srv-podman-gitlab-data
  - hostPath:
      path: /srv/podman/gitlab/logs
      type: Directory
    name: srv-podman-gitlab-logs
  - hostPath:
      path: /srv/podman/gitlab/conf
      type: Directory
    name: srv-podman-gitlab-conf
status: {}

система:

# podman generate systemd 71fc2b2a5c63
# pod-71fc2b2a5c6346f0c1c86a2dc45dbe78fa192ea02aac001eb8347ccb8c043c26.service
# autogenerated by Podman 1.6.4
# Thu Jul 29 15:23:28 EDT 2020

[Unit]
Description=Podman pod-71fc2b2a5c6346f0c1c86a2dc45dbe78fa192ea02aac001eb8347ccb8c043c26.service
Documentation=man:podman-generate-systemd(1)
Requires=container-781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3.service container-da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864.service
Before=container-781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3.service container-da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864.service

[Service]
Restart=on-failure
ExecStart=/usr/bin/podman start db40ab8bf84bf35141159c26cb6e256b889c7a98c0418eee3c4aa683c14fccaa
ExecStop=/usr/bin/podman stop -t 10 db40ab8bf84bf35141159c26cb6e256b889c7a98c0418eee3c4aa683c14fccaa
KillMode=none
Type=forking
PIDFile=/var/run/containers/storage/overlay-containers/db40ab8bf84bf35141159c26cb6e256b889c7a98c0418eee3c4aa683c14fccaa/userdata/conmon.pid

[Install]
WantedBy=multi-user.target
# container-da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864.service
# autogenerated by Podman 1.6.4
# Thu Jul 29 15:23:28 EDT 2020

[Unit]
Description=Podman container-da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864.service
Documentation=man:podman-generate-systemd(1)
RefuseManualStart=yes
RefuseManualStop=yes
BindsTo=pod-71fc2b2a5c6346f0c1c86a2dc45dbe78fa192ea02aac001eb8347ccb8c043c26.service
After=pod-71fc2b2a5c6346f0c1c86a2dc45dbe78fa192ea02aac001eb8347ccb8c043c26.service

[Service]
Restart=on-failure
ExecStart=/usr/bin/podman start da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864
ExecStop=/usr/bin/podman stop -t 10 da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864
KillMode=none
Type=forking
PIDFile=/var/run/containers/storage/overlay-containers/da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864/userdata/conmon.pid

[Install]
WantedBy=multi-user.target
# container-781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3.service
# autogenerated by Podman 1.6.4
# Thu Jul 29 15:23:28 EDT 2020

[Unit]
Description=Podman container-781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3.service
Documentation=man:podman-generate-systemd(1)
RefuseManualStart=yes
RefuseManualStop=yes
BindsTo=pod-71fc2b2a5c6346f0c1c86a2dc45dbe78fa192ea02aac001eb8347ccb8c043c26.service
After=pod-71fc2b2a5c6346f0c1c86a2dc45dbe78fa192ea02aac001eb8347ccb8c043c26.service

[Service]
Restart=on-failure
ExecStart=/usr/bin/podman start 781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3
ExecStop=/usr/bin/podman stop -t 10 781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3
KillMode=none
Type=forking
PIDFile=/var/run/containers/storage/overlay-containers/781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3/userdata/conmon.pid

[Install]
WantedBy=multi-user.target

Мутаассифона, ба ҷуз аз кор кардани контейнерҳо, воҳиди тавлидшуда барои systemd дигар коре намекунад (масалан, тоза кардани контейнерҳои кӯҳна ҳангоми аз нав оғоз кардани чунин хидмат), аз ин рӯ шумо бояд чунин чизҳоро худатон илова кунед.

Аслан, Подман барои санҷидани контейнерҳо, интиқол додани конфигуратсияҳои кӯҳна барои docker-compose кифоя аст ва сипас ба сӯи Кубернетес, агар лозим бошад, дар кластер равед ё алтернативаи истифодаи осонтар ба Docker гиред.

кт

Лоиҳа ба архив рафт тақрибан шаш моҳ пеш аз сабаби он, ки RedHat онро харидааст, бинобар ин ман дар бораи он муфассалтар таваққуф намекунам. Умуман, он таассуроти хеле хуб гузошт, вале нисбат ба Докер ва аз ин хам бештар ба Подман он ба комбайн монанд аст. Инчунин тақсимоти CoreOS дар болои rkt сохта шуда буд (гарчанде ки онҳо дар аввал Docker доштанд), аммо он низ пас аз хариди RedHat ба охир расид.

Плас

Бештар як лоиҳа, ки муаллифи он танхо мехост контейнерхо созад ва идора кунад. Аз рӯи ҳуҷҷатҳо ва кодҳо, муаллиф ба стандартҳо риоя накардааст, балки танҳо тасмим гирифт, ки татбиқи худро нависад, ки дар асл, ӯ кардааст.

натиҷаҳои

Вазъият бо Кубернетес хеле ҷолиб аст: аз як тараф, бо Docker шумо метавонед кластерро ҷамъ кунед (дар ҳолати тӯда), ки бо он шумо ҳатто муҳити истеҳсолиро барои муштариён идора карда метавонед, ин махсусан барои дастаҳои хурд (3-5 нафар) дуруст аст. ), ё бо сарбории умумии хурд ё набудани хоҳиши фаҳмидани нозукиҳои таъсиси Kubernetes, аз ҷумла барои бори баланд.

Подман мутобиқати пурраро таъмин намекунад, аммо он як бартарии муҳим дорад - мутобиқат бо Kubernetes, аз ҷумла асбобҳои иловагӣ (buildah ва дигарон). Аз ин рӯ, ман ба интихоби асбоб барои кор чунин муносибат хоҳам кард: барои дастаҳои хурд ё бо буҷаи маҳдуд - Docker (бо режими эҳтимолии тӯда), барои таҳияи худ дар ҳости шахсии худ - рафиқон Подман ва барои ҳама - Кубернетес.

Ман боварӣ надорам, ки вазъият бо Docker дар оянда тағир намеёбад, охир онҳо пешраванд ва инчунин оҳиста-оҳиста қадам ба қадам стандартизатсия мекунанд, аммо Подман бо ҳама камбудиҳояш (танҳо дар Linux кор мекунад, кластер нест, монтаж ва дигар амалҳо қарорҳои тарафи сеюм мебошанд) оянда равшантар аст, бинобар ин ман ҳамаро даъват мекунам, ки ин бозёфтҳоро дар шарҳҳо муҳокима кунанд.

PS 3 август мо оғоз мекунем "Курси видеоии Dockerки дар он бо кори у бештар шинос шудан мумкин аст. Мо тамоми асбобҳои онро таҳлил хоҳем кард: аз абстраксияҳои асосӣ то параметрҳои шабака, нозукиҳои кор бо системаҳои гуногуни амалиётӣ ва забонҳои барномасозӣ. Шумо бо технология шинос мешавед ва мефаҳмед, ки Docker-ро дар куҷо ва чӣ гуна беҳтар истифода бурдан мумкин аст. Мо инчунин мисолҳои таҷрибаи беҳтаринро мубодила хоҳем кард.

Нархи фармоиши пеш аз баровардан: 5000 рубл. Барномаи "Docker Video Course" -ро пайдо кардан мумкин аст дар саҳифаи курс.

Манбаъ: will.com

Илова Эзоҳ