Мой первый Docker!

Опубликовано admin - ср, 07/06/2022 - 22:21

Docker

Сколько статей, но не из всех из них у меня получилось собрать более -менее рабочий Docker

Итак. Для чего он нужен. Он необходим для быстрого развертывания однообразного окружения для разработки разных приложений, к примеру на php и mysql. 

В результате прочтения Вас будет полностью настроенный Docker для php, symfony, mysql. 

Для начала его использования необходим установить. У меня Ubuntu (команда uname -a):

Linux alex-X470 5.13.0-52-generic #59~20.04.1-Ubuntu SMP Thu Jun 16 21:21:28 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux

Устанавливаем Docker.

Подробно об этом сказано  на официальном сайте https://docs.docker.com/engine/install/ubuntu/.

Приведём основные команды и поясним их.

Для начала удалим предыдущие версии Docker:

sudo apt-get remove docker docker-engine docker.io containerd runc

Далее устанавливаем через дополнительные пакеты необходимы для работы Docker:

 sudo apt-get update
 sudo apt-get install \
    ca-certificates \
    curl \
    gnupg \
    lsb-release

и репозиторий:

sudo mkdir -p /etc/apt/keyrings
 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
 echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Без Doсker Engine работать не будет:

 sudo apt-get update
 sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin

Эти команды устанавливают "Docker Engine".

Помимо этого, нам нужен Docker Compose. Подробно об этом написано в Install Docker Compose.

После это у Вас будет доступна информация о Docker:

$ docker -v
Docker version 19.03.8, build afacb8b
$ docker-compose -v
docker-compose version 1.25.4, build 8d51620a

Если Вы собираетесь устанавливать Docker Desktop, то при его установке Docker compose устанавливается самостоятельно.

Далее с чего начать. Это с создания директории в которой будут запускаться и создаваться контейнеры Docker. В моем случае это директория docker-test/.

Имя директории используется в Docker, поэтому выберите что-нибудь попроще (сразу скажу оно необходимо для связывания сетей в Docker). 

Наша структура будет выглядеть следующим образом:

Docker

 

Nginx

Код из nginx/default.conf:

server {

    listen 80;
    index index.php;
    server_name localhost;
    root /var/www/docker-test/public;
    error_log /var/log/nginx/project_error.log;
    access_log /var/log/nginx/project_access.log;

    location / {
        try_files $uri /index.php$is_args$args;
    }

    location ~ ^/index\\.php(/|$) {
        fastcgi_pass php:9000;
        fastcgi_split_path_info ^(.+\\.php)(/.*)$;
        include fastcgi_params;

        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        fastcgi_param DOCUMENT_ROOT $realpath_root;

        fastcgi_buffer_size 128k;
        fastcgi_buffers 4 256k;
        fastcgi_busy_buffers_size 256k;

        internal;
    }

    location ~ \\.php$ {
        return 404;
    }

}

Здесь хотелось бы особо выделить строку:

fastcgi_pass php:9000;

php - это имя контейнера (см. код ниже docker-compose.yml)

Код из nginx/nginx.conf:

http {

        ##
        # Basic Settings
        ##

        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        types_hash_max_size 2048;
        # server_tokens off;
        client_max_body_size 100m;
        server_names_hash_bucket_size 64;
        # server_name_in_redirect off;

        proxy_connect_timeout       600;
        proxy_send_timeout          600;
        proxy_read_timeout          600;
        send_timeout                600;

        include /etc/nginx/mime.types;
        default_type application/octet-stream;

        ##
        # SSL Settings
        ##

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
        ssl_prefer_server_ciphers on;

        ##
        # Gzip Settings
        ##


        gzip on;


        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;
}

Код файла php/Dockerfile:

FROM php:8.0-fpm

RUN apt update \
    && apt install -y zlib1g-dev g++ git libicu-dev zip libzip-dev libmagickwand-dev libmagickcore-dev \
        libfreetype6-dev \
        libjpeg62-turbo-dev \
        libpng-dev \
    && docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install intl opcache pdo pdo_mysql gd \
    && pecl install apcu \
    && docker-php-ext-enable apcu \
    && docker-php-ext-configure zip \
    && docker-php-ext-install zip \
    && docker-php-ext-install exif \
    && pecl install imagick \
    && docker-php-ext-enable imagick

RUN cd /usr/local/etc/php/conf.d/ && \
  echo 'memory_limit = -1' >> /usr/local/etc/php/conf.d/docker-php-ram-limit.ini
RUN apt-get update && apt-get install -y nodejs \
    -y npm \
    && npm install --global yarn

WORKDIR /var/www/docker-test

RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

RUN curl -sS https://get.symfony.com/cli/installer | bash
RUN mv /root/.symfony/bin/symfony /usr/local/bin/symfony
RUN git config --global user.email "eap1985@rambler.ru" \
    && git config --global user.name "eap1985"

Первая  строка может содержать версию образа php, в данным случае это php версии 8. К примеру можно заменить на 7 версию:

FROM php:7.4-fpm

RUN apt update \
    && apt install -y zlib1g-dev g++ git libicu-dev zip libzip-dev libmagickwand-dev libmagickcore-dev \
        libfreetype6-dev \
        libjpeg62-turbo-dev \
        libpng-dev \
    && docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install intl opcache pdo pdo_mysql gd \
    && pecl install apcu \
    && docker-php-ext-enable apcu \
    && docker-php-ext-configure zip \
    && docker-php-ext-install zip \
    && docker-php-ext-install mysqli \
    && docker-php-ext-install exif \
    && pecl install imagick \
    && docker-php-ext-enable imagick

RUN cd /usr/local/etc/php/conf.d/ && \
  echo 'memory_limit = -1' >> /usr/local/etc/php/conf.d/docker-php-ram-limit.ini
RUN apt-get update && apt-get install -y nodejs \
    -y npm \
    && npm install --global yarn

WORKDIR /var/www/docker-test

RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

RUN git config --global user.email "eap1985@rambler.ru" \
    && git config --global user.name "eap1985"

Иные образы можно найти по адресу https://hub.docker.com/_/php

Обратите внимание на WORKDIR /var/www/docker-test и команды RUN. Последние две строки заменить своими данными. Данный код является стандартным, он размещен в https://hub.docker.com/_/php. Дополнительно вы можете указать следующий с настройками php для библиотеки GD:

FROM php:7.4-fpm
RUN apt-get update && apt-get install -y \
		libfreetype6-dev \
		libjpeg62-turbo-dev \
		libpng-dev \
	&& docker-php-ext-configure gd --with-freetype --with-jpeg \
	&& docker-php-ext-install -j$(nproc) gd

Директории app (создается для symfony, указано ниже), mysql, docker создаются самостоятельно при запуске команды sudo docker-compose up.

Дополнительно можно указать настойки для php-fpm (файл app.pool.conf содержит php-fpm настройки):

RUN rm /usr/local/etc/php-fpm.d/docker.conf \
    && rm /usr/local/etc/php-fpm.d/www.conf \
    && rm /usr/local/etc/php-fpm.d/www.conf.default \
    && rm /usr/local/etc/php-fpm.d/zz-docker.conf \
    && rm -rf /var/www/html

ADD app.pool.conf /usr/local/etc/php-fpm.d/app.pool.conf

Код файла docker-compose.yml:

version: '3.2'

services:
  database:
    container_name: database
    image: mysql
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: my-secret-pw
      MYSQL_ROOT_HOST: "%"
      MYSQL_DATABASE: symfony_docker
      MYSQL_USER: symfony
      MYSQL_PASSWORD: symfony
    ports:
      - '4306:3306'
    volumes:
      - /data/mysql:/var/lib/mysql
      - ./container-my.cnf:/etc/my.cnf
    networks:
      - docker-test_default
  php:
    container_name: php
    build:
      context: ./php
    ports:
      - '9000:9000'
    volumes:
      - ./app:/var/www/docker-test
    depends_on:
      - database
    links:
      - database
    networks:
      - docker-test_default

  nginx:
    container_name: nginx
    image: nginx:stable-alpine
    ports:
      - '8081:80'
    volumes:
      - ./app:/var/www/docker-test
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
      - phpmyadmin_data:/var/www/html/:ro
    networks:
      - docker-test_default
    depends_on:
      - database
      - phpmyadmin

  # phpMyAdmin container
  phpmyadmin:
    # Use phpmyadmin/phpmyadmin:5.0.2 image
    image: phpmyadmin/phpmyadmin:5.0.2
    # Connect to "my-network" network, as defined below
    networks:
      - docker-test_default
    # Map port 8080 on the host to port 80 inside the container
    # Syntax is: "HOST_PORT:CONTAINER_PORT"
    ports:
      - "8085:80"
    # Pass a list of environment variables to the container
    environment:
      PMA_HOST: database
    # Wait for "mysql" container to start first
    depends_on:
      - database

networks:
  docker-test_default:

volumes:
  phpmyadmin_data:

Если Вам необходим открыть сайт без порта в имени домена, используйте:

ports:
      - 80:80

Файл содержит четыре контейнера с соответствующими настройками:

  1. database
  2. docker-test_phpmyadmin_1
  3. php
  4. nginx

Также обратите внимание на секции volumes.

Volumes are the preferred mechanism for persisting data generated by and used by Docker containers

Другими словами они сохраняют информацию и заполняют ею при запуске контейнера наш Docker.

При наличии данного файла можно попробовать запустить наш Docker, командой:

sudo docker-compose up

запуск сопровождается следующим:

alex@alex-X470:/var/www/docker-test$ sudo docker-compose up --force-recreate
Creating network "docker-test_docker-test_default" with the default driver
Creating database ... done
Creating docker-test_phpmyadmin_1 ... done
Creating php                      ... done
Creating nginx                    ... done
Attaching to database, docker-test_phpmyadmin_1, php, nginx
database      | 2022-07-06 16:58:22+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.29-1.el8 started.
php           | [06-Jul-2022 16:58:23] NOTICE: fpm is running, pid 1
database      | 2022-07-06 16:58:22+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
nginx         | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
nginx         | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
php           | [06-Jul-2022 16:58:23] NOTICE: ready to handle connections
nginx         | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
database      | 2022-07-06 16:58:22+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.29-1.el8 started.
nginx         | 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
phpmyadmin_1  | phpMyAdmin not found in /var/www/html - copying now...
database      | '/var/lib/mysql/mysql.sock' -> '/var/run/mysqld/mysqld.sock'
phpmyadmin_1  | Complete! phpMyAdmin has been successfully copied to /var/www/html
....................................

Сейчас по адресу http://localhost:8081/ станет доступным сервер php, а по адресу http://localhost:8085 phpMyAdmin. Ура ?!

Дополнительные команды, которые Вам понадобятся:

Команда выводит все контейнеры Docker:

sudo docker ps

Команда удаляет все контейнеры Docker:

sudo docker container prune

 Команда запускает контейнеры разом:

sudo docker-compose up --force-recreate

  Команда останавливает контейнеры разом:

sudo docker-compose down

  Команда для запуска в образ:

docker-compose exec php /bin/bash 

Команда для инспектирования образа:

docker  inspect "имя контейнера"

Типичные ошибки при сборке первого Docker.

mysqli::real_connect(): php_network_getaddresses: getaddrinfo failed: Temporary failure in name resolution  mysqli::real_connect(): (HY000/2002):

Эта ошибка возникала у меня при запуске phpMyAdmin. Связна она, по мнению многих, с не указанием директивы networks в файле docker-compose.yml.

networks:
      - docker-test_default

Команда docker-compose exec

Данная команда очень существенная для разработки. Документация по ней имеется на сайте docs.dokcer.com

Через нее происходит выполнение команд внутри контейнера.

docker-compose exec php /bin/bash

К примеру, в этом случае у вас имеется доступ к php, где мы можем запустить symfony cli:

symfony check:requirements

Если все в порядке, то дальше можно перейти к установке приложения symfony:

symfony new .

После чего можно увидеть по адресу рабочий стол symfony:

Docker Symfony

Другой разновидностью может выступать команда:

docker-compose exec database /bin/bash

 С ее помощью мы получаем доступ к контейнеру database.  А внутри его к mysql.

Например:

mysql -u root -p symfony_docker

Таким образом мы настроили первый Docker.

Сохранение данных в Docker

Сохранение данных в Docker является не очень простым делом как оказалось. Осуществляется оно через volumes.

Если Вы внимательно посмотрите на четыре предыдущих контейнера, то в каждом из них имеется директива volumes. К примеру в секции mysql:

    volumes:
      - ./data/mysql:/var/lib/mysql

Это означает, что данные сохраняются из var/lib/mysq в ./data/mysql. Это необходимо знать, так как без этого, не сохраните и не замените то, что вы наработали в mysql.

Для сохранения можно воспользоваться командой: docker run --rm --volumes-from $container ubuntu tar -zcvf- /var/lib/mysql > /tmp/backup.tar.gz Замените $container на имя или ID вашего контейнера.

Для сохранения базы из Docker используйте следующую команду:

docker exec CONTAINER_id /usr/bin/mysqldump -uusername --password=yourpassword databasename> backup.sql

Для импорта в windows у меня не совсем подошла команда, хотя она вполне работает:

Get-Content backup.sql | docker exec -i database mysql -uroot -pmy-secret-pw symfony_docker

Лучше сперва скопировать данные:

docker container cp .\backup.sql database:/backup.sql

 а затем использовать:

docker exec -it database bash
mysql -uroot -pmy-secret-pw symfony_docker < backup.sql

или 

sudo docker-compose exec database /bin/bash
mysql -uroot -pmy-secret-pw symfony_docker < backup.sql

В случае, если необходимо пересобрать контейнер:

docker-compose build --no-cache

Возможные проблемы.

Иногда возникают проблемы с правами, например при очистке кэша директорий symfony. Мне помог следующий код в файле Dockerfile в php директории:

RUN mkdir -p var/cache/prod var/cache/dev var/cache/test var/log \
   && chown -R www-data:www-data var/ \
   && chmod -R ug+rwX var/
USER www-data

В качастве альтернативы возможден вариант:

version: '3.5'
services:
  dokuwiki:
    user: "${UID}" # set a specific user id so the container can write in the data dir
    image: bitnami/dokuwiki:latest
    ports:
      - '8080:8080'
    volumes:
      - '/home/manuel/docker/dokuwiki/data:/bitnami/dokuwiki/'
    restart: unless-stopped
    expose:
      - "8080"

В следующей статье я расскажу как сохранять данные с помощью официального сайта Docker.

Взаимосвязанные материалы

# 1. Мой первый Docker! (среда, июля 6, 2022 - 22:21 ),
Итак. Для чего он нужен. Он необходим для быстрого развертывания однообразного окружения для разработки разных приложений, к примеру на php и mysql о чем мы будем говорить далее. читать...

Комментарии

На разработку сайта! Скидки до 20%!