Недавно я настраивал веб-сервер Apache в связке с 1С. Причём веб-сервер находился на отдельном Linux хосте внутри Docker контейнера. Поделюсь своим опытом и дам пошаговую инструкцию.
Эта статья написана в апреле 2018 года и проверена на версии платформы 1С 8.3.11.3034. Далее рассматриваю подключение к информационной базе 1С в серверном варианте, не в файловом.
Почему именно Apache, именно под Linux и именно в Docker? Оставлю этот вопрос за рамками данной статьи.
Про Apache и про Linux слышали, наверное, все. А вот про Docker, который сильно набирает популярность последнее время, поделюсь кратким руководством на русском для общего понимания: http://guides.hexlet.io/docker/
Взаимодействие Apache и сервера 1С
В двух словах напомню схему взаимодействия веб-сервера Apache и сервера 1С, которая отлично описана в документации к 1С и миллионе статей, аналогичных этой.
Мы устанавливаем веб-сервер Apache и добавляем в его настройки (в файл httpd.conf) специальный модуль wsap24.so. Этот модуль разработан компанией 1С и он доступен в дистрибутиве сервера 1С под Linux.
Далее всё в том же httpd.conf мы даём указания веб-серверу, что все запросы начинающиеся с определённого пути (например /BuhBase) нужно обрабатывать с помощью специального обработчика 1c-application, реализованного в модуле wsap24.so.
Соответственно, когда на веб-сервер Apache приходит входящий HTTP запрос удовлетворяющий заданному пути, например, http://<ip>/BuhBase/, в дело вступает обработчик 1c-application. Оно в свою очередь заглядывает в некий файл .vrd, внутри должны быть настройки подключения к 1С.
Обычно vrd файл генерируется в процессе выполнения процедуры «публикации на веб сервере» из конфигуратора или с помощью консольной утилиты webinst. В данном случае конфигуратор нам не поможет, ведь мы планируем запускать веб-сервер Apache совсем на другом хосте, нежели сервер 1С, да ещё и внутри Docker контейнера. Консольную утилиту webinst тоже трогать не будем, опишем файл default.vrd вручную, благо там нужно всего несколько строк в минимальном варианте, нет смысла заморачиваться с запуском чего-бы то ни было дополнительного.
Итак, если default.vrd файл есть и в нём присутствуют верные настройки подключения к серверу 1С, то модуль запущенный внутри Apache подключается по TCP к серверу 1С.
При этом сам сервер 1С может находиться совсем на другой машине и на другой операционной системе. Это не важно, главное чтобы Apache смог достучаться до сервера 1С по TCP.
Соберём всю конфигурацию по шагам
Шаг 1.
Устанавливаем Docker на локальную машину разработчика (для удобства проверки и отладки) и на целевую Linux машину, где мы собственно и хотим запустить веб-сервер.
Docker работает и на Linux, и на macOS и на Windows. Скорее всего, на машине разработчика (на вашей машине) стоит Windows. Я лично не проверял описанные ниже шаги под Windows, теоретически всё должно сработать, но что-то пойдёт не так, можно не тратить силы и нервы и сделать всё непосредственно на Linux сервере или в локальной виртуальной машине (например, с помощью VirtualBox).
Подробные инструкции по установке Docker: https://docs.docker.com/install/
На сервер будем ставить Docker CE (Community Edition), в частности для Ubuntu инструкция здесь: https://docs.docker.com/install/linux/docker-ce/ubuntu/
При установке на Linux не забудем про этот важный шаг, который описан на отдельной странице в документации: https://docs.docker.com/install/linux/linux-postinstall/
Шаг 2.
Создадим директорию для нашего проекта и скачаем в неё дистрибутив 1С Сервер для Linux: https://releases.1c.ru -> Технологическая платформа 8.3 -> Cервер 1С:Предприятия (64-bit) для DEB-based Linux-систем
Скачается файл с расширением .tar.gz - переименуем его в deb64.tar.gz.
Шаг 3.
Создадим файл с настройками подключения к 1С: default.vrd
Я привожу пример минимального vrd файла в котором по умолчанию опубликованы все веб-сервисы, все http сервисы и стандартный REST интерфейс (OData).
<?xml version="1.0" encoding="UTF-8"?>
<point xmlns="http://v8.1c.ru/8.2/virtual-resource-system"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
base="/BuhBase"
ib="Srvr=Serv1C;Ref=BuhBase"
enableStandardOData="true">
<ws publishExtensionsByDefault="true" />
<httpServices publishByDefault="true" publishExtensionsByDefault="true"/>
</point>
Обратите внимание на строку подключения, замените имя сервера 1С (Serv1C) и имя информационной базы (BuhBase) на свои.
Если вы ранее уже публиковали свою базу на веб-сервере (не важно на каком: IIS или Apache, Windows или Linux, с помощью конфигуратор или с помощью webinst), у вас точно должен быть .vrd файл, поищите в публичных директориях веб-сервера и используйте его.
Шаг 4.
Возьмём стандартный конфиг от Apache (httpd.conf) и добавим к нему несколько строк в конец (полный пример: https://github.com/pqr/docker-apache-1c-example/blob/master/httpd.conf)
LoadModule _1cws_module /opt/1cv8/x86_64/8.3.19.1229/wsap24.so
# 1c publication
Alias "/BuhBase" "/usr/local/apache2/htdocs/BuhBase/"
<Directory "/usr/local/apache2/htdocs/BuhBase/">
AllowOverride All
Options None
Require all granted
SetHandler 1c-application
ManagedApplicationDescriptor "/usr/local/apache2/htdocs/BuhBase/default.vrd"
</Directory>
Таким образом мы указываем веб-северу, что запросы по пути /BuhBase нужно обслуживать с помощью обработчика (SetHandler) 1c-application.
Тут же указывается и путь к default.vrd. На данном этапе всех этих путей пока нет (и не будет, они будут внутри Docker контейнера).
Шаг 4.
Создадим файл с именем Dockerfile (без расширения) со следующим содержанием:
FROM httpd:2.4
# Данный образ базируется на стандартном образе Debian+Apache 2.4: https://store.docker.com/images/httpd
# Копируем дистрибутив в директорию dist
COPY deb64.tar.gz /dist/deb64.tar.gz
# Разархивируем дистрибутив
RUN tar -xzf /dist/deb64.tar.gz -C /dist \
# и устанавливаем пакеты 1С в систему внутри контейнера
&& dpkg -i /dist/*.deb \
# и тут же удаляем исходные deb файлы дистрибутива, которые нам уже не нужны
&& rm /dist/*.deb
# Копируем внутрь контейнера заранее подготовленный конфиг от Apache
COPY httpd.conf /usr/local/apache2/conf/httpd.conf
# Копируем внутрь контейнера заранее подготовленный конфиг с настройками подключения к серверу 1С
COPY default.vrd /usr/local/apache2/htdocs/BuhBase/default.vrd
Шаг 5.
Собираем образ командой:
docker build -t my-apache-1c .
Опция -t my-apache-1c присваивает собранному образу имя, чтобы в дальнейшем его было удобнее запуcкать. Если не указать -t, то запускать придётся по сгенерированному уникальному ID образа, что не очень удобно.
Также обратите внимание, что в конце идёт пробел и точка. Эта точка обязательна - это так называемый «контекст». В данном случае мы указываем, что контекстом является текущая директория. Более подробно, что такое контекст и зачем он нужен подробно описано в документации: https://docs.docker.com/engine/reference/builder/
Шаг 6.
Запускаем контейнер из только что созданного образа командой:
docker run --add-host Serv1C:192.168.1.15 --publish 80:80 my-apache-1c
Разберём эту строку по частям:
--add-host Serv1C:192.168.1.15 – здесь мы явно указали докеру, что за именем сервера Serv1C скрывается IP адрес 192.168.1.15 (подставьте свои значения). Имя сервера Serv1C мы использовали выше в default.vrd. Этот эквивалентно тому, как если бы мы прописали эту связь в знаменитый hosts файл. Но внутри контейнера нельзя поправить hosts файл, нужно действовать через параметр командной строки --add-host.
А почему бы сразу не указать IP адрес в default.vrd? Я пробовал, но при проверке в браузере платформа 1С выдавала ошибку и, честно говоря, я не разобрался в проблеме. При подключении по имени хоста (Serv1C) проблем не было.
--publish 80:80 – сообщаем докеру, запросы к хост-машине на порт 80 нужно перенаправлять в контейнер на порт 80 (внутри контейнера слушает Apache). Иногда на хост-машине порт 80 может быть уже занят, например, на этом же Linux сервере запущен какой-то сайт или на машине разработчика стоит локальный веб-сервер, тогда делаем так: --publish <любой свободный порт на хост-машине>:80, например: --publish 8000:80
Последним параметром идёт имя образа (my-apache-1c) на основе которого запускать контейнер. Образ с таким именем мы уже создали на предыдущем шаге.
После запуска этой команды в окне терминала появятся логи процесса Apache. Терминал не закрываем. Если закрыть, контейнер будет остановлен.
Шаг 7.
Проверяем.
Сначала проверяем Apache в целом: http://localhost – должны увидеть сообщение «It Works!»
Почему localhost? Мы сейчас находимся на своей собственной машине (на компьютере разработчика) где запустили Docker контейнер, соответственно для нас он запущен локально.
Если все эксперименты проводятся сразу на Linux сервере, то пробовать нужно, соответственно, по адресу Linux сервера, например, http://192.168.1.10 или http://linux-host
Если при запуске контейнера был указан какой-то особый порт для хост-машины, то проверять нужно на нём, например, http://localhost:8000
Далее проверим как открывается пользовательский веб-интерфейс информационной базы: http://localhost/BuhBase/
Проверим стандартный REST интерфейс (OData): http://localhost/BuhBase/odata/standard.odata/
Попробуем какой-нибудь веб-сервис (если в конфигурации такие есть): http://localhost/BuhBase/ws/MyWebService?wsdl
Всё должно отработать!
Теперь можно останавливать контейнер: Ctrl+C
Шаг 8.
Мы только что развернули Apache с модулем 1С в Docker контейнере на локальной машине (на машине разработчика). На деле это всё должно крутиться где-то на специально отведённом Linux сервере в виде демона.
Удобнее всего запускать контейнер на сервере с помощью утилиты docker-compose. Но для начала протестируем этот docker-compose опять же на локальной машине.
Устанавливаем docker-compose: https://docs.docker.com/compose/install/
Всё в той же директории проекта (где у нас уже есть Dockerfile, httpd.conf, и др.) создаём файл docker-compose.yml:
version: '3.4'
services:
apache-1c:
build: .
restart: always
ports:
- 80:80
extra_hosts:
- "Serv1C:192.168.1.15"
По сути здесь всё те же параметры, которые мы передавали в команду docker run.
Отличий три:
- Мы больше не придумываем и не указываем имя для нашего образа типа (my-apache-1c), вместо этого используем параметр build: . , т.е. docker-compose будет собирать образ на основе текущей директории (помните про контекст?) и тут же запускать контейнер на основе собранного образа
- restart: always - если по каким-то причинам Apache упадёт или весь сервер перезагрузится, то Docker автоматически перезапустит контейнер
- extra_hosts - это тоже самое, что и --add-host в параметрах команды docker run. Да, есть некая неконсистентность.
И запускаем контейнер с помощью новой для нас команды:
docker-compose up -d
Контейнер должен запуститься и уйти в фоновый режим (флаг -d). Проверяем все адреса в браузере как на предыдущем шаге.
Останавливаем контейнер (эту команду нужно выполнять в терминале, находясь в директории проекта):
docker-compose down
Шаг 9.
В реальности, пока мы тестировали сборку образов, меняли настройки, запускали контейнеры, мы наверняка прошли по шагам 3-7 много раз. При этом docker не удаляет с жесткого диска старые версии образов и контейнеров, они копились всё это время и теперь занимают место. Пришло время прибраться на машине (подробности в документации https://docs.docker.com/config/pruning/)
docker system prune
Шаг 10.
Важная часть любого проекта - это документация! Обязательно напишем README.md, например, такой: https://github.com/pqr/docker-apache-1c-example/blob/master/README.md
Поместим все файлы, кроме deb64.tar.gz, под систему контроля версий git, отправим в корпоративный репозиторий, чтобы не потерялось.
Шаг 11.
Копируем получившуюся директорию проекта на Linux сервер, заходим туда по ssh и, находясь в целевой директории, выполняем команду docker-compose up -d, проверяем в браузере.
Всё готово и работает на Linux сервере!
Что с обновлениями платформы 1С?
Качаем новый дистрибутив и копируем в директорию проекта под именем deb64.tar.gz.
В файле httpd.conf обновляем путь в строке: LoadModule _1cws_module /opt/1cv8/x86_64/8.3.19.1229/wsap24.so - обратите внимание на номер версии в пути, его нужно заменить на актуальную версию платформы, для которой мы сейчас настраиваем.
Далее копируем новый deb64.tar.gz и обновлённый httpd.conf на Linux на сервер в директорию проекта, останавливаем запущенный контейнер и тут же запускаем заново со специальным флагом --build:
docker-compose down && docker-compose up -d --build
А если несколько информационных баз?
Вариант А.
Значит нам понадобится подготовить несколько .vrd файлов, добавить инструкции по их копированию в Dockerfile и описать пути для веб-сервера в httpd.conf: на каждую базу свой путь, своя директория, свой .vrd файл.
Закидываем изменённый Dockerfile, httpd.conf и новые vrd файлы на сервер, останавливаем контейнер и запускаем заново с флагом --build:
docker-compose down && docker-compose up -d --build
Вариант Б.
На каждую информационную базу можно поднять свой отдельный контейнер. Это значит что директорию проекта нужно будет размножить по числу баз, внутри каждой сделать свои настройки в .vrd файле. Но при таком подходе не получится все контейнеры запустить одновременно на одному порту, придётся в каждом docker-compose.yml прописать свои порты, например, 8001:80 для первой базы, 8002:80 для второй базы и т.д.
У этого подхода, кстати, есть другое полезное свойство - внутри этих контейнеров могут быть различные версии модуля 1С (это нужно если у вас и серверов 1С несколько с разными версиями платформы).
Нужно поменять настройки подключения к 1С серверу в default.vrd?
docker-compose down && docker-compose up -d --build
Что осталось за кадром?
- В этой статье не описано как быть с файловыми базами. Черновой пример настроек привёл в комментариях под статьёй, но на деле его не проверял.
- После переноса файлов проекта с локальной машины на сервер всё может не заработать. Например, на сервере может быть закрыт порт 80 - надо проверять правила firewall, iptables и т.п. Могут быть и другие причины - как это всё отлаживать и куда смотреть (где логи?) остаётся за рамками статьи
- Если этот веб-сервер должен смотреть в интернет то нам обязательно нужен SSL сертификат для https соединения. Про то как настраивать https в Apache написано много статей. При использовании Apache внутри Docker по большому счёту всё настраивается точно также. Либо можно поставить reverse proxy с терминацией SSL, например, Træfik или Nginx. Вот этот Docker образ ещё и сертификаты от Let's Encrypt автоматически установит: https://hub.docker.com/r/umputun/nginx-le/
- В качестве базового образа мы использовали официальный httpd на базе Debian. Можно попробовать поиграться с более лёгким образом на базе Alpine.
Исходный код
Все файлы конфигурации описанные в этой статье можно найти в git репозитории: https://github.com/pqr/docker-apache-1c-example/ - принимаются Pull Requests.
Есть вопросы? Напишите мне, с удовольствием дополню статью, если что-то не понятно, есть пробелы в рассуждениях или какие-то шаги в вашем случае не сработали - попробуем разобраться вместе и дополним материал.