How to run nextcloud on Docker container?


In this post I established nextcloud server on Raspberry Pi 4.

But as you imagine this takes time to establish when you need to install Raspberry Pi OS again.
– You are Raspberry Pi geek, so you know this workload is not ignorable, right?

Then I solved this issue to do on Docker container.

This post is how to establish Nextcloud server by Dockerfile.
If you want docker-compose.yml, please access another post.

System structure

Let’s see below diagram.
Considering data backup/recovery, nextcloud program and data directory are mounted on host.

Contents of Dockerfile

I put Dockerfile on my github.

GitHub - kurofuku/nextcloud-container
Contribute to kurofuku/nextcloud-container development by creating an account on GitHub.

Let me share what is done one by one.


FROM		debian:latest

ENV		GID=1000 \

I chose base image as debian because I am familiar with Ubuntu.
However if you are used to Arch or Alpine or other distribution, of course you can use it.

Usually Docker container has only root user, but it is less secure because whatever you do you need to run as root.
So I created new user which UID/GID is 1000.

– This number is just kind of.

I put __USERNAME__ or __GROUPNAME__ or others to avoid putting real user name, group name or other sensitive information to Dockerfile.
You can decide these kind of parameters when you perform sudo docker build by using sed command.


“RUN” part is log part, so let me explain by deviding some parts.

Updating system, adding user, setting locale

RUN			\
# Update to latest
apt -y update && \
apt -y upgrade && \
# Install general packages
apt -y install htop sudo wget ssh apache2 && \
# Add user
groupadd -g ${GID} ${GROUPNAME} && \
useradd -g ${GROUPNAME} -m -s /bin/bash ${USERNAME} && \
echo "${USERNAME}:${PASSWORD}" | chpasswd && \
echo "${USERNAME}  ALL=(ALL)       ALL" >> /etc/sudoers && \
# Configure locale
apt -y install locales && \
sed -i -E 's/# (en_US.UTF-8)/\1/' /etc/locale.gen && \
locale-gen && \
echo "export LANG=en_US.UTF-8" >> ${HOME}/.bashrc && \

apt update/update is needless to say.
After that I install my favorite apps.
In this case nextcloud is deploied on apache, hence apache2 is installed.

Next is adding user.
Of course interactive style which is adduser cannot be used in Dockerfile, so I use useradd.

Finally setting up locale and reflect to .bashrc to apply user settings.
I set only English. If you want to add other languages, you can do it.


# Setup dotfiles
wget -O && \
bash ./ raspi && \
rm -f ./ && \

This part runs which is originally created by me.
If you have interest contents, you can read this article.

Adding package for nextcloud, setting up HTTPS

# Setup packages for nextcloud
apt -y install libapache2-mod-php php-sqlite3 php-zip php-xml php-mbstring php-gd php-curl && \
# Setup HTTPS
sed -i -E 's/#ServerName __DOMAIN_NAME__/' /etc/apache2/sites-available/000-default.conf && \
apt -y install certbot python-certbot-apache && \

In this part I do below.

Installing packages which is needed by nextcloud
Modifying server name in apache settings
Installing packages for HTTPS which is done by Let's Encrypt

I use sqlite database.
Firstly I thought mysql to use, but mysql is difficult to handle in Docker environment.
So I changed to use sqlite.

sqlite is easy to use because database is just file so you can easily backup/restore.

If this is for business I want to use mysql or postgresql, but this is personal use, so it is enough with sqlite.

Installing mod-security

# Setup mod-security2
apt -y install libapache2-mod-security2 && \
cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf && \
# Exclude PUT in nextcloud
echo "<Directory /var/www/html/nextcloud/>" > /etc/modsecurity/nextcloud.conf && \
echo "	SecRuleRemoveById 911100" >> /etc/modsecurity/nextcloud.conf && \
echo "</Directory>" >> /etc/modsecurity/nextcloud.conf && \

Now it installs mod-security.
For more detail please take a look this article.
Rule 911100 is detecting “PUT” method, but PUT is used by nextcloud.
So I added exception rule to ignore PUT method only under nextcloud directory.

SSH configuration

# Enable password authentication for SSH
sed -i -e 's/^PasswordAuthentication no/PasswordAuthentication yes/' /etc/ssh/sshd_config && \
echo "Build complete." 

Now setting up SSH configuration.
Lastly print “Build complete.” then building image is done!


# Starting SSH server and apache
service ssh restart && \
service apache2 restart && \

# Obtaining certificate for HTTPS
certbot run -n --apache --email "__MAIL_ADDRESS__" --agree-tos --domains "__DOMAIN_NAME__" && \

# Connecting HTTPS certificate and domain name(www included)
certbot certonly -n --expand --webroot -w /var/www/html \
-d "__DOMAIN_NAME__" -d "__WWW_DOMAIN_NAME__" && \

# Limiting cipher suites which has high strength
sed -i -E 's/SSLCipherSuite (.*)/SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:\
/etc/letsencrypt/options-ssl-apache.conf && \

# Removing to use SSL and TLS1.0/1.1
sed -i -E 's/SSLProtocol (.*)/SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1/' \
/etc/letsencrypt/options-ssl-apache.conf && \

# Restarting apache
service apache2 restart && \
/bin/bash --login


Running certbot command to do them
 - Obtaining HTTPS certificate
 - Connecting HTTPS certificate to apache configuration
Limiting cipher suites which has high strength
Restarting apache

It gets HTTPS certificate in ENTRYPOINT, so after 3 months certificate will be expired.
If this is the case you can simply restart container.

I take this style because for some reason this container sometimes dies and needs to be run again.
I haven’t concluded why container dies but for countermeasure I take this style.

Ideally running cron in container is the best.

sudo docker build

To build docker image, please run them.
I think you can change image name which is “nextcloud-image” in below snippets.

It uses sed command to replace user name, group name, password, domain name and so on.
Lastly passing contents of Dockerfile to “sudo docker build” by using “-” option which stands for standard input.

# To make sure we are in clean environment
sudo rm -rf nextcloud && unzip -q && sudo chown -R www-data:www-data nextcloud && \
sudo rm -rf nextcloud_data && mkdir nextcloud_data && sudo chown www-data:www-data nextcloud_data && \

# Replacing user name or other parameters by sed for some times -> sudo docker build
sed 's/__GROUPNAME__/myuser/' docker-file/Dockerfile.template | sed 's/__USERNAME__/mygroup/' | \
sed 's/__PASSWORD__/mypassword/' | sed 's/__DOMAIN_NAME__/mydomain\.com/' | \
sed 's/__WWW_DOMAIN_NAME__/www\.mydomain\.com/' | sed 's/__MAIL_ADDRESS__/abcde@hotmail\.com/' | \
sudo docker build -t nextcloud-image -

sudo docker run

To run container please do these snippets.
It mounts these directories.

nextcloud program: /var/www/html/nextcloud/
nextcloud data /var/www/nextcloud_data/

I set “–restart=always” options to start automatically when this container dies or system reboot.
You can change image name which is “nextcloud-image” in this sample.

sudo docker run -dit \
-v `pwd`/nextcloud:/var/www/html/nextcloud \
-v `pwd`/nextcloud_data:/var/www/nextcloud_data \
--restart=always \
-p 80:80 -p 443:443 -p 22:22 \

In conclusion

How was it?

Perhaps this sample is not complete suitable for you.

But you can use some parts to help your activity!

Put your comment on this site directly or via SNS if you enjoyed!


Copied title and URL