Недавно потестировал Nexcloud вообще, см. NextCloud: установка сервера на Debian с NGINX и PHP-FPM, и клиента на Arch Linux – в целом понравилось, работает – можно попробовать мигрировать с Dropbox на него.
Сегодня запустим Nextcloud полностью в Docker, на сервере с Debian 10 в Digital Ocean.
К серверу подключён отдельный диск, на котором будут все данные Nextcloud, что бы можно легко забекапить/перенести их.
Для запуска создадим Docker Compose стек, в котором будут:
- NGINX: проксирующий веб-сервер
- Lets Encrypt: клиент для генерации и обновления SSL-сертификатов
- MariaDB: сервер баз данных для хранения настроек Nextcloud
- Nextcloud: контейнер с PHP-FPM и исходным кодом Nextclou
Документация – тут>>>.
Для SSL используем клиент Lets Encrypt из docker-образа docker-letsencrypt-nginx-proxy-companion.
Установка Docker и Docker Compose
Устанавливаем Docker:
И Docker Compose (проверьте версию – download/1.24.1/ на странице релизов):
[email protected]:~# curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
Создаём каталог для файла Compose:
Приступаем к созданию стека.
Запуск Nexcloud
nginx-proxy
Создаём каталоги для файлов NGINX и Lets Encrypt:
[email protected]:/data/nextcloud# mkdir -p /data/nextcloud/nginx/{certs,vhost.d,html}
Создаём файл /opt/nextcloud/nextcloud-compose.yml
, начнём с конца – добавляем сеть:
networks:
nextcloud_network:
Теперь добавляем контейнер с nginx-proxy
, который использует эту сеть, монтируем каталоги и приводим файл к такому виду:
version: '3'
services:
nginx-proxy:
image: jwilder/nginx-proxy:alpine
labels:
- "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy=true"
container_name: nextcloud-proxy
networks:
- nextcloud_network
ports:
- 80:80
- 443:443
volumes:
- /data/nextcloud/nginx/vhost.d:/etc/nginx/vhost.d:rw
- /data/nextcloud/nginx/html:/usr/share/nginx/html:rw
- /data/nextcloud/nginx/certs:/etc/nginx/certs:ro
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/tmp/docker.sock:ro
restart: unless-stopped
networks:
nextcloud_network:
Строка labels: com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy=true будет использоваться контейнером с Lets Encrypt, что бы определить “свой” прокси-сервис.
Каталоги, которые монтируем:
/etc/nginx/certs
: для хранения сертификатов и приватных ключей (read-only для контейнера nginx-proxy
, т.к. файлы создаются контейнером с клиентом Lets Encrypt).
/etc/nginx/vhost.d
: для настройки виртуалхостов
/usr/share/nginx/html
: для верификации домена при генерации сертификата
Запускаем:
Creating nextcloud-proxy ... done
Attaching to nextcloud-proxy
nextcloud-proxy | WARNING: /etc/nginx/dhparam/dhparam.pem was not found. A pre-generated dhparam.pem will be used for now while a new one
nextcloud-proxy | is being generated in the background. Once the new dhparam.pem is in place, nginx will be reloaded.
nextcloud-proxy | forego | starting dockergen.1 on port 5000
nextcloud-proxy | forego | starting nginx.1 on port 5100
nextcloud-proxy | Generating DH parameters, 2048 bit long safe prime, generator 2
nextcloud-proxy | dockergen.1 | 2019/11/27 08:15:10 Generated '/etc/nginx/conf.d/default.conf' from 1 containers
nextcloud-proxy | dockergen.1 | 2019/11/27 08:15:10 Running 'nginx -s reload'
nextcloud-proxy | dockergen.1 | 2019/11/27 08:15:10 Watching docker events
nextcloud-proxy | dockergen.1 | 2019/11/27 08:15:10 Contents of /etc/nginx/conf.d/default.conf did not change. Skipping notification 'nginx -s reload'
nextcloud-proxy | 2019/11/27 08:15:41 [notice] 41#41: signal process started
nextcloud-proxy | This is going to take a long time
nextcloud-proxy | dhparam generation complete, reloading nginx
И пробуем подключиться к хосту:
HTTP/1.1 503 Service Temporarily Unavailable
Server: nginx/1.17.5
Date: Wed, 27 Nov 2019 07:57:28 GMT
Content-Type: text/html
Content-Length: 197
Connection: keep-alive
Отлично. Ошибка 503 нам сейчас не важна, т.к. кроме NGINX ещё ничего не запущено.
Let’s Encrypt Docker
Добавляем сервис в наш Compose-файл:
...
letsencrypt:
image: jrcs/letsencrypt-nginx-proxy-companion
container_name: nextcloud-letsencrypt
depends_on:
- nginx-proxy
networks:
- nextcloud_network
volumes:
- /data/nextcloud/nginx/vhost.d:/etc/nginx/vhost.d:rw
- /data/nextcloud/nginx/html:/usr/share/nginx/html:rw
- /data/nextcloud/nginx/certs:/etc/nginx/certs:rw
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
restart: unless-stopped
...
Перезапускаем стек:
Starting nextcloud-proxy ... done
Creating nextcloud-letsencrypt ... done
Attaching to nextcloud-proxy, nextcloud-letsencrypt
nextcloud-proxy | Custom dhparam.pem file found, generation skipped
nextcloud-proxy | forego | starting dockergen.1 on port 5000
nextcloud-proxy | forego | starting nginx.1 on port 5100
nextcloud-proxy | dockergen.1 | 2019/11/27 08:31:01 Contents of /etc/nginx/conf.d/default.conf did not change. Skipping notification 'nginx -s reload'
nextcloud-proxy | dockergen.1 | 2019/11/27 08:31:01 Watching docker events
nextcloud-proxy | dockergen.1 | 2019/11/27 08:31:01 Contents of /etc/nginx/conf.d/default.conf did not change. Skipping notification 'nginx -s reload'
nextcloud-proxy | dockergen.1 | 2019/11/27 08:31:02 Received event start for container 2f40fa5f50ea
nextcloud-proxy | dockergen.1 | 2019/11/27 08:31:02 Contents of /etc/nginx/conf.d/default.conf did not change. Skipping notification 'nginx -s reload'
nextcloud-letsencrypt | Generating a RSA private key
nextcloud-letsencrypt | ...........................................................................................................................++++
nextcloud-letsencrypt | ...........++++
nextcloud-letsencrypt | writing new private key to '/etc/nginx/certs/default.key.new'
nextcloud-letsencrypt | -----
nextcloud-letsencrypt | Info: a default key and certificate have been created at /etc/nginx/certs/default.key and /etc/nginx/certs/default.crt.
nextcloud-letsencrypt | Info: Creating Diffie-Hellman group in the background.
nextcloud-letsencrypt | A pre-generated Diffie-Hellman group will be used for now while the new one
nextcloud-letsencrypt | is being created.
nextcloud-letsencrypt | Generating DH parameters, 2048 bit long safe prime, generator 2
nextcloud-letsencrypt | Reloading nginx proxy (2e665ad175d4e2dbd270b4616bbe5d0e1c5f78421d25da55d163cc15836e859c)...
nextcloud-letsencrypt | 2019/11/27 08:31:03 Generated '/etc/nginx/conf.d/default.conf' from 2 containers
nextcloud-letsencrypt | 2019/11/27 08:31:03 [notice] 34#34: signal process started
nextcloud-letsencrypt | 2019/11/27 08:31:03 Generated '/app/letsencrypt_service_data' from 2 containers
nextcloud-letsencrypt | 2019/11/27 08:31:03 Running '/app/signal_le_service'
nextcloud-letsencrypt | 2019/11/27 08:31:04 Watching docker events
nextcloud-letsencrypt | 2019/11/27 08:31:04 Contents of /app/letsencrypt_service_data did not change. Skipping notification '/app/signal_le_service'
nextcloud-letsencrypt | Sleep for 3600s
nextcloud-letsencrypt | This is going to take a long time
nextcloud-letsencrypt | Info: Diffie-Hellman group creation complete, reloading nginx.
nextcloud-letsencrypt | Reloading nginx proxy (2e665ad175d4e2dbd270b4616bbe5d0e1c5f78421d25da55d163cc15836e859c)...
nextcloud-letsencrypt | 2019/11/27 08:31:12 Contents of /etc/nginx/conf.d/default.conf did not change. Skipping notification ''
nextcloud-letsencrypt | 2019/11/27 08:31:12 [notice] 54#54: signal process started
Let’s Encrypt сгенерировал сертификат – проверяем:
total 12
-rw-r--r-- 1 root root 1870 Nov 27 08:31 default.crt
-rw-r--r-- 1 root root 3272 Nov 27 08:31 default.key
-rw-r--r-- 1 root root 424 Nov 27 08:31 dhparam.pem
Проверяем доступность по HTTPS/443:
curl: (60) SSL certificate problem: self signed certificate
More details here: https://curl.haxx.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
Окей – соединение проходит, но ругается на сертификат. Исправим это, когда будем запускать контейнер с nextcloud
.
Пока можно использовать curl -k
:
HTTP/2 503
server: nginx/1.17.5
date: Wed, 27 Nov 2019 08:32:58 GMT
content-type: text/html
content-length: 197
Прежняя 503, но главное – коннект на HTTPS проходит, тут всё работает.
MariaDB в Docker
Теперь добавим контейнер с MariaDB.
Что бы хранить данные постоянно – создаём каталог:
Добавляем описание сервиса в Compose:
...
mysql:
image: mariadb
container_name: nextcloud-mysql
networks:
- nextcloud_network
volumes:
- /data/nextcloud/mysql:/var/lib/mysql
- /etc/localtime:/etc/localtime:ro
environment:
- [email protected]
- [email protected]
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
restart: unless-stopped
...
Запускаем сервис:
...
nextcloud-mysql | 2019-11-27 09:16:38+00:00 [Note] [Entrypoint]: Database files initialized
nextcloud-mysql | 2019-11-27 09:16:38+00:00 [Note] [Entrypoint]: Starting temporary server
nextcloud-mysql | 2019-11-27 09:16:38+00:00 [Note] [Entrypoint]: Waiting for server startup
nextcloud-mysql | 2019-11-27 9:16:38 0 [Note] mysqld (mysqld 10.4.10-MariaDB-1:10.4.10+maria~bionic) starting as process 121 ...
nextcloud-mysql | 2019-11-27 9:16:38 0 [Note] InnoDB: Using Linux native AIO
nextcloud-mysql | 2019-11-27 9:16:38 0 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
nextcloud-mysql | 2019-11-27 9:16:38 0 [Note] InnoDB: Uses event mutexes
nextcloud-mysql | 2019-11-27 9:16:38 0 [Note] InnoDB: Compressed tables use zlib 1.2.11
nextcloud-mysql | 2019-11-27 9:16:38 0 [Note] InnoDB: Number of pools: 1
nextcloud-mysql | 2019-11-27 9:16:38 0 [Note] InnoDB: Using SSE2 crc32 instructions
nextcloud-mysql | 2019-11-27 9:16:38 0 [Note] mysqld: O_TMPFILE is not supported on /tmp (disabling future attempts)
nextcloud-mysql | 2019-11-27 9:16:38 0 [Note] InnoDB: Initializing buffer pool, total size = 256M, instances = 1, chunk size = 128M
nextcloud-mysql | 2019-11-27 9:16:38 0 [Note] InnoDB: Completed initialization of buffer pool
nextcloud-mysql | 2019-11-27 9:16:38 0 [Note] InnoDB: If the mysqld execution user is authorized, page cleaner thread priority can be changed. See the man page of setpriority().
nextcloud-mysql | 2019-11-27 9:16:38 0 [Note] InnoDB: 128 out of 128 rollback segments are active.
nextcloud-mysql | 2019-11-27 9:16:38 0 [Note] InnoDB: Creating shared tablespace for temporary tables
nextcloud-mysql | 2019-11-27 9:16:38 0 [Note] InnoDB: Setting file './ibtmp1' size to 12 MB. Physically writing the file full; Please wait ...
nextcloud-mysql | 2019-11-27 9:16:38 0 [Note] InnoDB: File './ibtmp1' size is now 12 MB.
nextcloud-mysql | 2019-11-27 9:16:38 0 [Note] InnoDB: Waiting for purge to start
nextcloud-mysql | 2019-11-27 9:16:38 0 [Note] InnoDB: 10.4.10 started; log sequence number 139827; transaction id 21
nextcloud-mysql | 2019-11-27 9:16:38 0 [Note] Plugin 'FEEDBACK' is disabled.
nextcloud-mysql | 2019-11-27 9:16:38 0 [Note] InnoDB: Loading buffer pool(s) from /var/lib/mysql/ib_buffer_pool
nextcloud-mysql | 2019-11-27 9:16:38 0 [Warning] 'user' entry '
[email protected]' ignored in --skip-name-resolve mode.
nextcloud-mysql | 2019-11-27 9:16:38 0 [Warning] 'user' entry '@de5e3e9dd106' ignored in --skip-name-resolve mode.
nextcloud-mysql | 2019-11-27 9:16:38 0 [Warning] 'proxies_priv' entry '@%
[email protected]' ignored in --skip-name-resolve mode.
nextcloud-mysql | 2019-11-27 9:16:38 0 [Note] InnoDB: Buffer pool(s) load completed at 191127 9:16:38
nextcloud-mysql | 2019-11-27 9:16:38 0 [Note] Reading of all Master_info entries succeeded
nextcloud-mysql | 2019-11-27 9:16:38 0 [Note] Added new Master_info '' to hash table
nextcloud-mysql | 2019-11-27 9:16:38 0 [Note] mysqld: ready for connections.
nextcloud-mysql | Version: '10.4.10-MariaDB-1:10.4.10+maria~bionic' socket: '/var/run/mysqld/mysqld.sock' port: 0 mariadb.org binary distribution
nextcloud-mysql | 2019-11-27 09:16:39+00:00 [Note] [Entrypoint]: Temporary server started.
...
Проверяем данные на диске:
total 122936
-rw-rw---- 1 systemd-coredump systemd-coredump 32768 Nov 27 09:17 aria_log.00000001
-rw-rw---- 1 systemd-coredump systemd-coredump 52 Nov 27 09:17 aria_log_control
-rw-rw---- 1 systemd-coredump systemd-coredump 6176 Nov 27 09:17 ib_buffer_pool
-rw-rw---- 1 systemd-coredump systemd-coredump 12582912 Nov 27 09:17 ibdata1
-rw-rw---- 1 systemd-coredump systemd-coredump 50331648 Nov 27 09:17 ib_logfile0
-rw-rw---- 1 systemd-coredump systemd-coredump 50331648 Nov 27 09:16 ib_logfile1
-rw-rw---- 1 systemd-coredump systemd-coredump 12582912 Nov 27 09:17 ibtmp1
-rw-rw---- 1 systemd-coredump systemd-coredump 0 Nov 27 09:16 multi-master.info
drwx------ 2 systemd-coredump systemd-coredump 4096 Nov 27 09:17 mysql
drwx------ 2 systemd-coredump systemd-coredump 4096 Nov 27 09:17 nextcloud
drwx------ 2 systemd-coredump systemd-coredump 4096 Nov 27 09:16 performance_schema
Всё есть.
Пробуем подключиться локально:
ОК, работает.
Nextcloud
И, наконец-то – добавляем сам Nextcloud.
Создаём каталоги для него:
[email protected]:~# mkdir -p /data/nextcloud/app/{config,custom_apps,data,themes,html}
Обновляем Compose:
...
nextcloud-app:
image: nextcloud:latest
container_name: nextcloud-app
networks:
- nextcloud_network
depends_on:
- letsencrypt
- nginx-proxy
- mysql
volumes:
- /data/nextcloud/app/html:/var/www/html
- /data/nextcloud/app/config:/var/www/html/config
- /data/nextcloud/app/custom_apps:/var/www/html/custom_apps
- /data/nextcloud/app/data:/var/www/html/data
- /data/nextcloud/app/themes:/var/www/html/themes
- /etc/localtime:/etc/localtime:ro
environment:
- VIRTUAL_HOST=cloud.example.org.ua
- LETSENCRYPT_HOST=cloud.example.org.ua
- [email protected]
restart: unless-stopped
...
Переменная VIRTUAL_HOST
используется nginx-proxy
для выбора направления что и куда проксировать, а LETSENCRYPT_HOST
– самим Lets Encrypt контейнером для выбора имени хоста, для которого будет сгенерирован сертификат. См. документацию тут>>>.
Запускаем стек:
[email protected]:/opt/nextcloud# docker-compose -f nextcloud-compose.yml up --force-recreate
Recreating nextcloud-proxy ... done
Recreating nextcloud-mysql ... done
Recreating nextcloud-letsencrypt ... done
Creating nextcloud-app ... done
Attaching to nextcloud-mysql, nextcloud-proxy, nextcloud-letsencrypt, nextcloud-app
...
Проверяем по HTTPS, но уже без -k
, т.е. выполняем валидацию сертификата:
HTTP/2 200
server: nginx/1.17.5
...
И в браузере:

Настройка Nextcloud
Далее всё выполняется аналогично NextCloud: установка сервера на Debian с NGINX и PHP-FPM, и клиента на Arch Linux, с той разницей, что адрес сервера баз данных указываем в том виде, в котором он указан в Compose-файле, т.е. в данном примере mysql – Docker сам выполнит DNS-resolution по имени контейнера в его IP из сети nextcloud_network
:

И:

Tags и полный docker-compose файл
Перед тем, как закончить со всем этим – давайте обновим Compose-файл, и вместо latest зададим конкретные теги (версии) для запускаемых сервисов – хорошая практика для любого production-ready решения.
На момент написания теги:
- jwilder/nginx-proxy:0.4.0
- jrcs/letsencrypt-nginx-proxy-companion:v1.12
- mariadb:10.4.10
- nextcloud:17.0.1-apache
Весь файл сейчас выглядит так:
version: '3'
services:
nginx-proxy:
image: jwilder/nginx-proxy:0.4.0
labels:
- "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy=true"
container_name: nextcloud-proxy
networks:
- nextcloud_network
ports:
- 80:80
- 443:443
volumes:
- /data/nextcloud/nginx/vhost.d:/etc/nginx/vhost.d:rw
- /data/nextcloud/nginx/html:/usr/share/nginx/html:rw
- /data/nextcloud/nginx/certs:/etc/nginx/certs:ro
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/tmp/docker.sock:ro
restart: unless-stopped
letsencrypt:
image: jrcs/letsencrypt-nginx-proxy-companion:v1.12
container_name: nextcloud-letsencrypt
depends_on:
- nginx-proxy
networks:
- nextcloud_network
volumes:
- /data/nextcloud/nginx/vhost.d:/etc/nginx/vhost.d:rw
- /data/nextcloud/nginx/html:/usr/share/nginx/html:rw
- /data/nextcloud/nginx/certs:/etc/nginx/certs:rw
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
restart: unless-stopped
mysql:
image: mariadb:10.4.10
container_name: nextcloud-mysql
networks:
- nextcloud_network
volumes:
- /data/nextcloud/mysql:/var/lib/mysql
- /etc/localtime:/etc/localtime:ro
environment:
- [email protected]
- [email protected]
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
restart: unless-stopped
nextcloud-app:
image: nextcloud:17.0.1-apache
container_name: nextcloud-app
networks:
- nextcloud_network
depends_on:
- letsencrypt
- nginx-proxy
- mysql
volumes:
- /data/nextcloud/app/html:/var/www/html
- /data/nextcloud/app/config:/var/www/html/config
- /data/nextcloud/app/custom_apps:/var/www/html/custom_apps
- /data/nextcloud/app/data:/var/www/html/data
- /data/nextcloud/app/themes:/var/www/html/themes
- /etc/localtime:/etc/localtime:ro
environment:
- VIRTUAL_HOST=cloud.example.org.ua
- LETSENCRYPT_HOST=cloud.example.org.ua
- [email protected]
restart: unless-stopped
networks:
nextcloud_network:
Обновляем образы:
Пересоздаём стек:
[email protected]:/opt/nextcloud# docker-compose -f nextcloud-compose.yml up --force-recreate
Проверяем, что все файлы на месте.
systemd
Последним шагом – создаём systemd
unit-файл для сервиса, как описано в посте Linux: systemd сервис для Docker Compose, назовём его /etc/systemd/system/nextcloud.service
:
[Unit]
Description=Nextcloud stack
Requires=docker.service
After=docker.service
[Service]
Restart=always
WorkingDirectory=/opt/nextcloud
ExecStart=/usr/local/bin/docker-compose -f nextcloud-compose.yml up
ExecStop=/usr/local/bin/docker-compose -f nextcloud-compose.yml down
[Install]
WantedBy=multi-user.target
Запускаем сервис:
● nextcloud.service - Nextcloud stack
Loaded: loaded (/etc/systemd/system/nextcloud.service; disabled; vendor preset: enabled)
Active: active (running) since Wed 2019-11-27 13:56:37 UTC; 4s ago
Main PID: 16599 (docker-compose)
Tasks: 7 (limit: 1167)
Memory: 74.3M
CGroup: /system.slice/nextcloud.service
├─16599 /usr/local/bin/docker-compose -f nextcloud-compose.yml up
...
И добавляем в автозапуск:
Created symlink /etc/systemd/system/multi-user.target.wants/nextcloud.service → /etc/systemd/system/nextcloud.service.
Готово.