Nginx Proxy Manager swarm template¶
replaced
i moved to traefik, one name at a time, so the reverse proxy's routes live in git. npm is stopped, and will be retired once traefik has run on its own for a while.
Description¶
This template runs NPM, my reverse proxy.
State Considerations for SWARM¶
- This container has a database. The data, the certificates and the database are named binds on cephfs, see stack conventions.
- I restrict to 1 instance of each container to avoid database corruption from having two instances.
- Both services read their passwords from swarm secrets through entrypoint wrappers, see secrets.
- Leave hostname as db (name resolution works fine using this method).
- If you place the database in a different stack / want to use an existing database then both stacks need to share a network.
- A third service,
db-dump, dumps the database to/mnt/docker-cephFS/npm_dumpsat start and at :50 every hour, so every cephFS backup holds a consistent copy. It runs the database's image with the same script as wordpress's hourly dump. The folder has to exist before the first deploy (sudo mkdir -m 700 /mnt/docker-cephFS/npm_dumps). - The tables are Aria, which has no consistent read view, so the dump uses
--lock-tables: writers wait for it, readers carry on. The database is 0.5 MB and the dump takes under a second, and only npm's admin side uses the database, while nginx proxies from the config files npm generates. - If
mysqldump --routinesfails withCannot load from mysql.proc(error 1728), the system tables were made by an older MariaDB and never upgraded.mariadb-upgradeinside the db container fixes that; take a dump first. - The image creates two anonymous accounts when it starts on an empty data folder,
''@'localhost'and one for that first container's hostname, and never removes them. Nothing uses them, andmysql -u npminside the db container is matched to the anonymous one instead ofnpm, so I dropped both, with the grants they leave ontestdatabases. As root in the db container:SELECT Host FROM mysql.user WHERE User = ''gives the hostname, thenDROP USER ''@'localhost', ''@'<hostname>'; DELETE FROM mysql.db WHERE User = ''; FLUSH PRIVILEGES;.
Network Considerations¶
This publishes 80, 443 and 81 (admin) as 180, 1443 and 181, so the admin UI is at swarmIP:181.
Placement Considerations¶
cephfs allows the replica to run on any node. I hard set 1 replica (even though that's default) to avoid corruption of the database. Not sure it will corrupt, this is just my own caution.
compose.yml, 119 lines, 5 notes
each in the code opens a note on that line. download compose.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | |
- a shell reads the swarm secret into
DB_MYSQL_PASSWORD, thenexecs/init, the image's s6 entrypoint. a missing secret makes the container exit before npm starts. - the router forwards the WAN's 80 and 443 to 180 and 1443 on the nodes, which keeps the nodes' own 80 and 443 free. 181 is the admin UI.
- a shell reads the root password and the npm user's password from swarm secrets, then
execs/scripts/run.sh, the mariadb-aria entrypoint. the user's password isnpm_db_password_v2, the secret the app reads, so a new database gets the password npm logs in with. - the hourly dump: the db image, running the same
db-dump.shas wordpress's instead of mariadb.--lock-tables, because npm's Aria tables have no consistent read view. - named binds on the cephfs mount.
npm_db,npm_dataandnpm_lemust exist before the first deploy, or the task refuses to start.
db-dump.sh: the dump sidecar's script, the same as wordpress's, 37 lines
This page started as a gist: the original, with its comments