Today I'm going to focus on publishing the existing version of this service and test how it works.

Moving old files

This project was based on previous work, so I had to remove the old files from the project, instead, I moved those to another (more relevant) repo for safe-keeping, later I figured out that much of that code is reusable.

Creating a simple docker-compose

I believe in seeing the effects immediately, therefore I decided to work on the deployment scripts before even touching the code. This way I can first deploy the existing version then continuously work on new features and "integrate" them into the running code.

Docker compose

Creating the first version is quite simple, there is already a Dockerfile previously used by K8s:

version: '3'
services:
  seen:
    image: seen
    build: .
    ports:
      - 8080:8080

Run using docker-compose up

This way I could check the actual app on http://localhost:8080, which would give me Cannot GET / but still... :)

I had forgotten to rename things in the Dockerfile in the previous steps when moving the files around, so I had to do some small changes to make it work.

Adding database

I basically copy-pasted the pg12 code I had before on docker-compose to create the database, but when I ran docker-compose up the app was trying to connect to localhost instead of the database container.

seen_1      | Error: connect ECONNREFUSED 127.0.0.1:5432
seen_1      |     at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1139:16) {
seen_1      |   errno: -111,
seen_1      |   code: 'ECONNREFUSED',
seen_1      |   syscall: 'connect',
seen_1      |   address: '127.0.0.1',
seen_1      |   port: 5432
seen_1      | }

Turns out the issue was very simple, when I moved things to docker-compose I renamed some of the environment variables to use the same env file for both database and app. Unfortunately, I forgot to rebuild the image after changing the parameters in the app source.

To avoid this issue again, I created a very simple but useful script called script.sh:

docker-compose up --build

Database initialization

After the database was successfully created, it was time to add the DB schema to create the initial database tables.

CREATE TABLE receipts(
    name VARCHAR(256) PRIMARY KEY
);
CREATE TABLE receipt_records(
    receipt VARCHAR(256) REFERENCES receipts(name),
    record TEXT,
    timestamp TIMESTAMP DEFAULT current_timestamp
);

Then it's enough to mount it in the designated directory for initdb files for the Postgres Docker image, see https://hub.docker.com/_/postgres

    volumes:
      - database-data:/var/lib/postgresql/data/
      - ./schema.sql:/docker-entrypoint-initdb.d/0_init.sql

And finally the docker-compose.yaml looks like:

version: '3'
services:
  seen:
    image: seen
    build: .
    ports:
      - 127.0.0.1:8080:8080
    env_file:
      - database.env # configure postgres
    depends_on:
      - database
    networks:
      - database
  database:
    image: 'postgres:12' # use latest official postgres 12 version
    env_file:
      - database.env # configure postgres
    volumes:
      - database-data:/var/lib/postgresql/data/ # persist data even if container shuts down
      - ./schema.sql:/docker-entrypoint-initdb.d/0_init.sql
    expose:
      - 5432
    networks:
      - database

volumes:
  database-data:

networks:
  database:

I moved the above docker-compose file to my server and started the service with slight modifications to make it work on that server.

Usage

This is likely to change in the end drastically, but at the time of writing this post this is the behavior

/create/[name].png

Example: https://seen.lit.codes/create/example-1.png

This creates a new record in database and shows you a png file with a copy button which can be used to copy the image file and paste it to an email.

/[name].png

Example: https://seen.lit.codes/example-1.png

This is the link to the actual image file.

/stats/[name].png

Example: https://seen.lit.codes/stats/example-1.png

See who has visited that file, and their IP addresses.

/stats

Example: https://seen.lit.codes/stats

See all the existing files and their stats.