Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor docker deployment and user setup #863

Merged
merged 25 commits into from May 15, 2024

Conversation

kkovaletp
Copy link
Contributor

Fix #862, address #826, and maybe some other tickets: reimplemented the docker-compose user setup to enhance the product setup experience and cover much more cases:

  • extended original docker-compose example with many additional improvements
  • added .env and moved all user-changeable variables there
  • added Makefile with the most useful shortcuts to simplify product maintenance
  • documented all of this with inline comments and updated the Readme

Please feel free to give your feedback and ask questions if you have any.

Konstantin Koval added 2 commits July 7, 2023 10:21
…: reimplemented the docker-compose user setup to enhance product setup experience and cover much more cases.
@codecov
Copy link

codecov bot commented Jul 19, 2023

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 24.94%. Comparing base (4133694) to head (def5531).

❗ Current head def5531 differs from pull request most recent head d4d719c. Consider uploading reports for the commit d4d719c to get more accurate results

Additional details and impacted files
@@             Coverage Diff             @@
##           master     #863       +/-   ##
===========================================
- Coverage   56.43%   24.94%   -31.49%     
===========================================
  Files         196       96      -100     
  Lines       15601     4406    -11195     
  Branches      558        0      -558     
===========================================
- Hits         8804     1099     -7705     
+ Misses       6543     3053     -3490     
  Partials      254      254               
Flag Coverage Δ
api 24.94% <ø> (ø)
ui ?

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

…mple.yml, as it is defined in the Dockerfile; optimized Dockerfile combining all RUN directives of PROD stage into 1, which will produce single layer and save some space; added Dockerfile-dev, docker-compose-dev.yml, and new "dev" and "dev-down" directives into Makefile, which allows to setup development env in Docker. Instructions of how to use it are in comments at the beginning of Dockerfile-dev and docker-compose-dev.yml files
@kkovaletp
Copy link
Contributor Author

kkovaletp commented Aug 16, 2023

As a response to issue #876 I added the development environment setup. It could be enhanced by mounting the code folders to the Photoview container and running the server using dev server tools, like nodeamon, but these improvements require a good understanding of the code and dev environment, so if you see some benefits from that, as a developer, implement (and test) that from your side.

To get more details, please read the conversation in the #876. In case these dev server enhancements are implemented and you'd like to include them in this container setup, please provide me a detailed guide on how to replicate them inside containers and I'll add this to the PR.

@kkovaletp
Copy link
Contributor Author

While optimizing the Dockerfile, I noticed that Debian is used as a base image. While it is stable, it is old-fashioned and outdated compared to some newer Debian-based images (like Ubuntu). From my point of view, it is not an optimal base image. Does anybody have some objections against switching to ubuntu:latest? Maybe you see some even better options, taking stability and security into account.

… so that the image could be later run with non-root permissions and the app still be able to do needed operations in the FS
@c13mn14k
Copy link

c13mn14k commented Nov 6, 2023

While optimizing the Dockerfile, I noticed that Debian is used as a base image. While it is stable, it is old-fashioned and outdated compared to some newer Debian-based images (like Ubuntu). From my point of view, it is not an optimal base image. Does anybody have some objections against switching to ubuntu:latest? Maybe you see some even better options, taking stability and security into account.

I think both Debian and Ubuntu may be bloated for photoview, I'll try to write a Dockerfile using Alpine.

@c13mn14k
Copy link

c13mn14k commented Nov 6, 2023

Your PR looks like a piece of nice work! I have one issue with it though, I think introducing a Makefile has some serious drawbacks:

  • it adds another complexity layer - running docker through make feels weird and these commands in makefile could be just simply bash scripts.
  • It requires that a new user installs Make to run photoview through docker, and
  • that the user is familiar with Make.
  • Using Make (or other complexity layer) makes additional assumptions about user setup.
  • Commands used in Make do not simplify or speed up work much - that is, they are not really specific to Make - you could just as comfortably write a few scripts.
  • Using Make hides Docker from new users which can create debugging problem - I assume not everyone hosting photoview is a competent admin, and having to work not only with docker but also with make can add trouble for more users when something breaks.
  • Make has more than it should: docker system prune -f shouldn't be there.

For me Make shouldn't be presented as the go-to way to setup photoview with docker. That setup should require docker only. Using Make creates complexity (system complexity and complexity for users) and additional assumptions: about users' OS and users' setup.

As an example, my homeserver is very thin besides being a docker host - thanks to docker I don't have a lot of packages, including make. I also combine all services related to similar areas inside one folder, so I have photoview together with other media services in one compose.

My proposition is:

  • Restore Docker Compose as the recommended way to run photoview with docker, remove reference to make in this section of docs
  • Add documentation about Makefile as a section of setup: ## Getting started - Setup with Docker and Make.
  • (other solution) Delete makefile and move commands used there to
    • documentation
    • a few bash scripts inside a scripts/ folder

This is a small change, but I think important. Otherwise your PR looks like a very helpful change for new users!

@kkovaletp
Copy link
Contributor Author

@c13mn14k, thanks for your review and detailed feedback!
I'll think about your proposals and implement some changes, however, I disagree with removing Make completely:

  • I think that this is a common and convenient way to simplify user interaction: 1 simple-to-read file with all the scenarios vs a set of bash scripts (1 per scenario) or 1 script with more complex syntax and without auto-completion
  • Makefile doesn't hide anything: it is a plaintext file, easy to read, and more: documentation contains a directive to go through it and review the commands and scenarios in the scope of the initial setup - user is free to modify it or not use at all, running the commands directly
  • You did a review from your point of view, owning a server with minimal OS setup, and yes, from this point of view your comments and proposals look valid and logical. However, I believe that this is not a typical use case compared to a fully functional OS setup. Also, most probably, owners of such servers with a minimal OS are much more skilled, as managing it requires a deeper dive into the OS specifics.

…` target and enhanced comments in the Makefile; commented out the `docker system prune -f` with the comment about the command and why it is there; added optional and commented by default `7zz` commands to the `backup` section of the Makefile
@kkovaletp kkovaletp mentioned this pull request Dec 17, 2023
@kkovaletp
Copy link
Contributor Author

Set it temporary to Draft state to make sure it is aligned with the current product workflow

@kkovaletp
Copy link
Contributor Author

kkovaletp commented Mar 30, 2024

Action Items:

Konstantin Koval and others added 4 commits March 30, 2024 18:12
…docker-compose

# Conflicts:
#	docker-compose.example.yml
…rfile to build with less layers and run as non-root; mapped only Photoview related services to Watchtower by default instead of updating all running images on a host; added template for Postgres to the .env; reverted compose executable definition, so the new compose is called when present; added a tip about `lnav` to help
@kkovaletp
Copy link
Contributor Author

[ ] to review and try to implement Create a Development dockerfile #650 here, as the DEV dockerfile is already here

@jordy2254, would you be able to help me with this action item from the dev perspective?
As we've discussed earlier, right now the dev-docker file is logically different from the main one only by having a single-stage build procedure, so all the code and intermediate artifacts are available, as well as the build tools.

However, to provide a truly useful docker file, we need to replace the statically built executable web server binary with a dynamically rebuilding web server for development (like nodeamon for frontend and backend or an alternative tool).

For this type of change, I'd need a developer, who can configure the corresponding tools from our project's code perspective and provide the step-by-step guide for me together with all needed configs.

Then I'll use them to create frontend and backend docker files for developers in our project.

Alternatively, I'll exclude the dev-dockerfile functionality from the PR completely, so that later someone else can create a new PR for that.

@kkovaletp
Copy link
Contributor Author

This is a big PR with a lot of changes, so here is the proposed code review path to make it as clear and straightforward, as possible:
Readme > Dockerfile > .env > docker-compose > Makefile - in this way (I hope) you'll better understand the idea behind and the implementation.

Copy link
Member

@viktorstrate viktorstrate left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added some comments in the code.

Generally I think that the example is fairly nice. I don't have strong feelings on the Makefile, I think it's fine to have it as it can provide convenience to the user and they can choose to use it if they want. As long as the Makefile is not required to perform some actions and only for convenience. I'm maybe thinking about backups here.

My major concern is that the example is very complicated (because it does a lot of things). And it is also very opinionated. Maybe not everyone wants to use Watchtower or they have another solution that they want to use, the same goes for backups.

I think the old docker-compose.example.yml which only had the bare minimum to get Photoview up and running is much easier to approach for someone who might be new to Docker or wants to try Photoview for the first time.

One solution might be to keep the old and simple docker-compose.example.yml, but provide a fully featured and opinionated setup along with it, maybe we could add a README file to the example directory to explain how it works? Then we could add all the nice features that we want, including backup etc. without worrying about complexity for users who want to have their own setup.

I don't think we need to introduce breaking changes in this pull request, as all the changes don't need it or could easily be implemented in a way that doesn't.

Comment on lines +26 to +28
RUN npm ci --omit=dev --ignore-scripts \
# Build frontend
&& npm run build -- --base=$UI_PUBLIC_URL
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why merge these into one command. Wouldn't caching be more efficient by installing dependencies first. Then copy the source files afterwards. That way only npm run build needs to run when depdencies don't change?

COPY ui/package*.json /app/
RUN npm ci --omit=dev --ignore-scripts

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, we've discussed this topic in the Discord: https://discord.com/channels/794576839813234688/1223295288668717146/1229127778679390319

Here is my answer for transparency:
Regarding layers: building production image on CI won't benefit much (if at all) from build cache, as in our project merges to master happen not so often. Having a well-optimized image for users is much better, as it pulls faster and uses less space on the host. It is even more important for ARM-based systems, where usually system partition is limited in space and performance.
In the case of the PR testing CI job, I'm not sure how exactly the docker cache works in Github, but from my experience with other CI/CD services, the docker cache is related to the branch, so every new PR will start a new thread of cache and won't utilize the cache from other PRs or master, so here there are no benefits from having more layers too.

Dockerfile Outdated
COPY --from=api /app/photoview /app/photoview

ENV PHOTOVIEW_LISTEN_IP 127.0.0.1
ENV PHOTOVIEW_LISTEN_PORT 80
ENV PHOTOVIEW_LISTEN_PORT 8080
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a breaking change

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is required by the "run as non-root user" improvement. We discussed this here: #863 (comment)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure that this is the case for Docker environments as well?
I just found this post: https://forums.docker.com/t/non-root-user-able-to-bind-to-port-80-why/140524

Maybe we should make an issue keeping track of the changes that we want to make for version 3.0?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We discussed this as part of the @Omar007 port change proposal. While I can confirm that the recent version of Docker allows using 80 port by a non-root user inside a container, it is not clear, starting from which version of Docker this change is introduced.
I can assume that some Linux distros or devices with proprietary Linux distros might still provide an older Docker version, where this is not yet implemented.
So, making sure that Photoview works according to Linux best practices on all supported platforms, looks more beneficial than keeping port 80 with the hope that it will work correctly everywhere.
I don't see a negative impact of switching the port number. Please share your thoughts if there is something negative, related to this change.

Copy link

@Omar007 Omar007 May 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see @kkovaletp covered the reasoning already but @viktorstrate is also technically correct in that it can be 'breaking'.
If a user had been running as root or granted the required capabilities (or had been on a Docker version greater than ...?) and has never explicitly set PHOTOVIEW_LISTEN_PORT themselves at any point (which it would've been if they used the compose file) and where to just swap out the image, it would be 'breaking' in the sense that their port-forwards/mapping would stop working if they don't explicitly set PHOTOVIEW_LISTEN_PORT=80 when they update.

Since this is a defaults change but also one that is backward compatible (it does not require these users to change assigned permissions or capabilites; they could start dropping these now but they don't need to) and non-breaking if they use(d) the compose file, I wouldn't say this would require a major version bump, postponing to a major release or anything like that, but I would at the very least make sure this is mentioned on w/e the tag ends up being for people running custom deployments.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Omar007 for the explanation!
If we review the case, where a user updates an image, but doesn't update the compose and .env files (which doesn't make much sense from fixes and improvements delivery, but can happen in reality) nothing is going to break, as the compose file from the current master contains the PHOTOVIEW_LISTEN_PORT=80:

- PHOTOVIEW_LISTEN_PORT=80

Of course, if this line was removed or commented out, it wouldn't work, but that is not the recommended config.

BTW, while answering this comment, I noticed the hardcoded port in the EXPOSE and HEALTHCHECK, so I replaced it with the variable, then tested that it works fine with the 8080 and 80 values (setting 80 in the compose file for the same image)

Comment on lines +46 to +58
# devices:
## Uncomment next devices mappings if they are available in your host system
## Intel QSV
# - "/dev/dri:/dev/dri"
## Nvidia CUDA
# - "/dev/nvidia0:/dev/nvidia0"
# - "/dev/nvidiactl:/dev/nvidiactl"
# - "/dev/nvidia-modeset:/dev/nvidia-modeset"
# - "/dev/nvidia-nvswitchctl:/dev/nvidia-nvswitchctl"
# - "/dev/nvidia-uvm:/dev/nvidia-uvm"
# - "/dev/nvidia-uvm-tools:/dev/nvidia-uvm-tools"
## Video4Linux Video Encode Device (h264_v4l2m2m)
# - "/dev/video11:/dev/video11"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add this to the documentation website?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can if you'd want it to be there, but I don't see a benefit: the compose file is read every time the configuration is done, it is self-descriptive with the comments (as to me), putting it in the documentation creates a duplicate of the info with no additional value

@kkovaletp
Copy link
Contributor Author

My major concern is that the example is very complicated (because it does a lot of things).

Yes, this PR is 1 year old and includes fixes for many reported (and some not reported) issues in the project. It is not possible to fix all of them with a simpler file. Taking comments out of it is not an option, as users might not understand the logic and will make many configuration mistakes without the in-line explanations.

Maybe not everyone wants to use Watchtower or they have another solution that they want to use, the same goes for backups.

Sure, that is why Watchtower is marked as optional. The reason, why it is enabled by default, is to encourage users to use it and have always the latest images running. This will decrease the potential # of issues, submitted for previous builds, while there is a new build with the fix. However, if you see more benefits in getting it disabled (commented out) by default, please share your thoughts.

Backups are configured in the Makefile, which is optional. There is only a variable in the .env, which can be safely ignored as long as the Makefile's backup target is not called. I can add this to the comment of the var in the .env

I think the old docker-compose.example.yml which only had the bare minimum to get Photoview up and running is much easier to approach for someone who might be new to Docker or wants to try Photoview for the first time. One solution might be to keep the old and simple docker-compose.example.yml, but provide a fully featured and opinionated setup along with it

Yes, it is. But also, it doesn't contain many optimizations and fixes, so keeping it in the repo would create a false impression that both are equivalent from a fixes perspective and only the difference in advanced configuration with more features provided in this file, while it is not the case.

maybe we could add a README file to the example directory to explain how it works?

Now this Readme is included into the config files in the form of in-line comments, which makes these configs self-descriptive and straightforward to configure, while following the configuration path from the project's Readme. Extracting the comments to the external Readme wouldn't simplify the configs, but add more complexity to users, as they would need to constantly switch between the config and the Readme to understand how to modify it according to their cases.

I don't think we need to introduce breaking changes in this pull request, as all the changes don't need it or could easily be implemented in a way that doesn't.

1st of all, please let me know, what do you mean by "breaking changes"? I communicated with engineers, who understand it a bit differently.
You mentioned the change of the internal port inside the container, as a breaking change. What does it break exactly in the case of using the correct configs on the host (from this PR)? Another breaking change might be the requirement to use configs from this PR to make the new image work fine. And this is the only way possible to provide the fixes, implemented in the PR. The configs from the current master cannot be used in any case.

@kkovaletp
Copy link
Contributor Author

And thanks a lot for your review and the feedback provided, @viktorstrate )
I got straight to the point and forgot to type this(

@kkovaletp
Copy link
Contributor Author

Based on our recent discussion I set the photoview image tag to 2 - the current major version. This will prevent auto-updates to the next major version and enhance stability.
If this PR merge is going to trigger an increment of the major version, another PR with consistent version updates across the code would be required, including the tag in the compose file example as well.

@kkovaletp kkovaletp mentioned this pull request May 9, 2024
@kkovaletp kkovaletp linked an issue May 9, 2024 that may be closed by this pull request
@kkovaletp kkovaletp linked an issue May 9, 2024 that may be closed by this pull request
@kkovaletp kkovaletp changed the title Enhance docker-compose user setup Refactor docker deployment and user setup May 12, 2024
@kkovaletp
Copy link
Contributor Author

According to the discussion in the product's Discord about this PR and the future product development strategy in general, it looks like this PR is going to be merged in some undefined future (if it will be at all).
It fixes A LOT of issues, so I assume that many users are waiting for it. If you are one of them, I'd recommend you to check my fork: https://github.com/kkovaletp/photoview - it already contains all the fixes and improvements and will get more in the future

@viktorstrate
Copy link
Member

I really like the changes proposed in this PR, and I'm really sad to hear that this is getting dragged out so much and you start losing motivation. For me this change would be awesome if two things was changed:

  1. The port number was changed back to 80, but keep everything else (eg. running non-root). And then expect users to use an up to date version of Docker.
  2. The original bare minimum docker-compose.example.yml is added back in the root directory, for those who want to configure it themselves.

@kkovaletp
Copy link
Contributor Author

@viktorstrate, thanks for your feedback and the summary of your expectations. Here are my short comments on them (the long and detailed explanations are here in the thread or the Discord - I don't remember already):

  1. While it is not the best solution according to the Linux best practices, it works fine, so I can do this change
  2. I disagree with this, as the original compose file is buggy and cannot provide the same fixes as the new one. So, by providing both we'd create a huge misunderstanding for users and a false impression that they are equal at least from the quality level, and differ in functionality only, while it is not the case.

@viktorstrate
Copy link
Member

Can you elaborate and help me understand what things would cause misunderstandings for users?

I like to have a bare minimum unopinionated example for users that is quick and easy to understand, and the let the users chose.

@kkovaletp
Copy link
Contributor Author

kkovaletp commented May 14, 2024

@viktorstrate, instead of starting another iteration of the same discussion, I've created the minimal compose file using the new file as a source and removing (almost) everything optional from it. Also, I've updated the readme and mentioned it in the docker section.
Please check my last commit to this PR to find these changes.
Is this what you expected to get or do you still prefer the original compose file?

Copy link
Member

@viktorstrate viktorstrate left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks good to me now, thank you for making the changes :)

@kkovaletp
Copy link
Contributor Author

I've found some minor bugs in config and will push a fixing commit, so please don't merge yet

…ssions for storage folder; fix healthcheck command for postgres
@kkovaletp
Copy link
Contributor Author

I committed the fixes for the bugs, found y-day. Feel free to merge the PR.

@viktorstrate
Copy link
Member

Thank you! I will merge this one just to move forward.

A lot of changes has been made but nothing breaking so if we find issues later on, let's just handle and fix it then. If someone still have concerns with the changes here, feel free to open a new issue or start a discussion on Discord.

@viktorstrate viktorstrate merged commit 0193f77 into photoview:master May 15, 2024
7 checks passed
Roadmap automation moved this from Before next release to Done May 15, 2024
@kkovaletp kkovaletp deleted the Enhance-docker-compose branch May 15, 2024 10:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working discussion Raises questions that are up for discussion docker Related to deployment with Docker documentation Improvements or additions to documentation feature A new idea or feature high priority
Projects
6 participants