Недавно потестировал 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:
root@setevoy-do-nextcloud-production:~# curl https://get.docker.com/ | bash
И Docker Compose (проверьте версию — download/1.24.1/ на странице релизов ):
root@setevoy-do-nextcloud-production:~# curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
root@setevoy-do-nextcloud-production:~# chmod +x /usr/local/bin/docker-compose
Создаём каталог для файла Compose:
root@setevoy-do-nextcloud-production:~# mkdir /opt/nextcloud
root@setevoy-do-nextcloud-production:~# cd /opt/nextcloud/
Приступаем к созданию стека.
Запуск Nexcloud
nginx-proxy
Создаём каталоги для файлов NGINX и Lets Encrypt:
root@setevoy-do-nextcloud-production:/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
: для верификации домена при генерации сертификата
Запускаем:
root@setevoy-do-nextcloud-production:/opt/nextcloud# docker-compose -f nextcloud-compose.yml up
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
И пробуем подключиться к хосту:
[setevoy@setevoy-arch-work ~] $ curl -I cloud.example.org.ua
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
...
Перезапускаем стек:
root@setevoy-do-nextcloud-production:/opt/nextcloud# docker-compose -f nextcloud-compose.yml up
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 сгенерировал сертификат — проверяем:
root@setevoy-do-nextcloud-production:/data/nextcloud# ll /data/nextcloud/nginx/certs/
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:
[setevoy@setevoy-arch-work ~] $ curl -I https://cloud.example.org.ua
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
:
[setevoy@setevoy-arch-work ~] $ curl -kI https://cloud.example.org.ua
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.
Что бы хранить данные постоянно — создаём каталог:
root@setevoy-do-nextcloud-production:/data/nextcloud# mkdir /data/nextcloud/mysql
Добавляем описание сервиса в Compose:
...
mysql:
image: mariadb
container_name: nextcloud-mysql
networks:
- nextcloud_network
volumes:
- /data/nextcloud/mysql:/var/lib/mysql
- /etc/localtime:/etc/localtime:ro
environment:
- MYSQL_ROOT_PASSWORD=mysql-root-p@ssw0rd
- MYSQL_PASSWORD=nextcloud-p@ssw0rd
- 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 'root@de5e3e9dd106' 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 '@% root@de5e3e9dd106' 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.
...
Проверяем данные на диске:
root@setevoy-do-nextcloud-production:~# ll /data/nextcloud/mysql/
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
Всё есть.
Пробуем подключиться локально:
root@setevoy-do-nextcloud-production:/data/nextcloud# mysql -h localhost -u root
...
MariaDB [(none)]>
ОК, работает.
Nextcloud
И, наконец-то — добавляем сам Nextcloud.
Создаём каталоги для него:
root@setevoy-do-nextcloud-production:~# 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
- LETSENCRYPT_EMAIL=root@example.org.ua
restart: unless-stopped
...
Переменная VIRTUAL_HOST
используется nginx-proxy
для выбора направления что и куда проксировать, а LETSENCRYPT_HOST
— самим Lets Encrypt контейнером для выбора имени хоста, для которого будет сгенерирован сертификат. См. документацию тут>>> .
Запускаем стек:
root@setevoy-do-nextcloud-production:/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
, т.е. выполняем валидацию сертификата:
[setevoy@setevoy-arch-work ~] $ curl -I https://cloud.example.org.ua
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:
- MYSQL_ROOT_PASSWORD=mysql-root-p@ssw0rd
- MYSQL_PASSWORD=nextcloud-p@ssw0rd
- 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
- LETSENCRYPT_EMAIL=root@example.org.ua
restart: unless-stopped
networks:
nextcloud_network:
Обновляем образы:
root@setevoy-do-nextcloud-production:/opt/nextcloud# docker-compose -f nextcloud-compose.yml pull
Пересоздаём стек:
root@setevoy-do-nextcloud-production:/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
Запускаем сервис:
root@setevoy-do-nextcloud-production:~# systemctl start nextcloud
root@setevoy-do-nextcloud-production:~# systemctl status nextcloud
● 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
...
И добавляем в автозапуск:
root@setevoy-do-nextcloud-production:~# systemctl enable nextcloud
Created symlink /etc/systemd/system/multi-user.target.wants/nextcloud.service → /etc/systemd/system/nextcloud.service.
Готово.