mirror of
https://github.com/Screenly/Anthias.git
synced 2025-12-23 22:38:05 -05:00
chore: use multi-stage builds for server images in both development and production environments (#2117)
This commit is contained in:
4
.github/workflows/docker-test.yaml
vendored
4
.github/workflows/docker-test.yaml
vendored
@@ -69,13 +69,15 @@ jobs:
|
||||
- name: Build Containers
|
||||
run: |
|
||||
poetry run python tools/image_builder \
|
||||
--dockerfiles-only \
|
||||
--disable-cache-mounts \
|
||||
--service celery \
|
||||
--service redis \
|
||||
--service test
|
||||
|
||||
- name: Start the test container
|
||||
run: |
|
||||
docker compose -f docker-compose.test.yml up -d
|
||||
docker compose -f docker-compose.test.yml up -d --build
|
||||
|
||||
- name: Run the unit tests inside the container
|
||||
run: |
|
||||
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -56,3 +56,8 @@ db.sqlite3
|
||||
|
||||
# Django
|
||||
staticfiles/
|
||||
|
||||
# Static files
|
||||
static/js/anthias.js*
|
||||
static/js/settings.js*
|
||||
static/css/anthias.css*
|
||||
|
||||
@@ -48,6 +48,10 @@ EOF
|
||||
if [ "$START_SERVER" = true ]; then
|
||||
cd /usr/src/app
|
||||
|
||||
npm install && \
|
||||
npm run coffee-build && \
|
||||
npm run sass-build
|
||||
|
||||
./manage.py makemigrations
|
||||
./manage.py migrate --fake-initial
|
||||
./manage.py runserver 127.0.0.1:8080 &
|
||||
|
||||
@@ -27,6 +27,9 @@ fi
|
||||
|
||||
if [[ "$ENVIRONMENT" == "development" ]]; then
|
||||
echo "Starting Django development server..."
|
||||
npm install && \
|
||||
npm run coffee-build && \
|
||||
npm run sass-build
|
||||
./manage.py runserver 0.0.0.0:8080
|
||||
else
|
||||
echo "Generating Django static files..."
|
||||
|
||||
@@ -1,3 +1,28 @@
|
||||
{% if environment == 'production' %}
|
||||
FROM debian:bookworm as node-builder
|
||||
|
||||
{% if disable_cache_mounts %}
|
||||
RUN \
|
||||
{% else %}
|
||||
RUN --mount=type=cache,target=/var/cache/apt \
|
||||
{% endif %}
|
||||
apt-get update && \
|
||||
apt-get -y install --no-install-recommends \
|
||||
nodejs \
|
||||
npm
|
||||
|
||||
RUN mkdir -p /app
|
||||
WORKDIR /app
|
||||
|
||||
COPY package.json package-lock.json /app
|
||||
RUN npm install
|
||||
|
||||
COPY ./static/js/*.coffee /app/static/js/
|
||||
COPY ./static/sass/*.scss /app/static/sass/
|
||||
RUN npm run coffee-build && \
|
||||
npm run sass-build
|
||||
|
||||
{% endif %}
|
||||
{% include 'Dockerfile.base.j2' %}
|
||||
|
||||
COPY requirements/requirements.txt /tmp/requirements.txt
|
||||
@@ -12,6 +37,15 @@ RUN mkdir -p /usr/src/app
|
||||
COPY . /usr/src/app/
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
{% if environment == 'production' %}
|
||||
COPY --from=node-builder \
|
||||
/app/static/css/ \
|
||||
/usr/src/app/static/css/
|
||||
COPY --from=node-builder \
|
||||
/app/static/js/*.js* \
|
||||
/usr/src/app/static/js/
|
||||
{% endif %}
|
||||
|
||||
ENV GIT_HASH={{ git_hash }}
|
||||
ENV GIT_SHORT_HASH={{ git_short_hash }}
|
||||
ENV GIT_BRANCH={{ git_branch }}
|
||||
|
||||
@@ -159,30 +159,34 @@ We've also provided a [checklist](/docs/qa-checklist.md) that can serve as a gui
|
||||
|
||||
## Generating CSS and JS files
|
||||
|
||||
Anthias only supports compiling from the host container at the moment. You need to install the latest version
|
||||
of Node.js. We recommend to intall Node.js on Linux. You can use this [guide](https://nodejs.org/en/learn/getting-started/how-to-install-nodejs)
|
||||
to get started.
|
||||
To get started, you need to start the development server first. See this [section](#dockerized-development-environment)
|
||||
for details.
|
||||
|
||||
### Installing Node.js dependencies
|
||||
|
||||
Run the following command from the project root directory.
|
||||
|
||||
```bash
|
||||
$ npm install
|
||||
$ docker compose -f docker-compose.dev.yml exec anthias-server \
|
||||
npm install
|
||||
```
|
||||
|
||||
### Transpiling CSS from SASS
|
||||
|
||||
Open a new terminal session and run the following command:
|
||||
|
||||
```bash
|
||||
$ npm run sass-dev
|
||||
$ docker compose -f docker-compose.dev.yml exec anthias-server \
|
||||
npm run sass-dev
|
||||
```
|
||||
|
||||
### Transpiling JS from CoffeeScript
|
||||
|
||||
Open a new terminal session and run the following command:
|
||||
|
||||
```bash
|
||||
# You need to run this on a separate terminal session if you already ran the
|
||||
# script for transpiling SASS files.
|
||||
$ npm run coffee-dev
|
||||
$ docker compose -f docker-compose.dev.yml exec anthias-server \
|
||||
npm run coffee-dev
|
||||
```
|
||||
|
||||
### Closing the transpiler
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"coffee-dev": "coffee --compile --map --watch static/js/*.coffee",
|
||||
"sass-dev": "sass --watch static/sass/:static/css/"
|
||||
"sass-dev": "sass --watch static/sass/:static/css/",
|
||||
"coffee-build": "coffee --compile --map static/js/*.coffee",
|
||||
"sass-build": "sass static/sass/:static/css/"
|
||||
},
|
||||
"dependencies": {
|
||||
"bootstrap": "^4.3.1",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
1154
static/js/anthias.js
1154
static/js/anthias.js
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -1,138 +0,0 @@
|
||||
// Generated by CoffeeScript 1.12.7
|
||||
(function() {
|
||||
$().ready(function() {
|
||||
var toggle_chunk;
|
||||
$("#request-error .close").click(function(e) {
|
||||
return $("#request-error .alert").hide();
|
||||
});
|
||||
$("#btn-backup").click(function(e) {
|
||||
var btnText;
|
||||
btnText = $("#btn-backup").text();
|
||||
$("#btn-backup").text("Preparing archive...");
|
||||
$("#btn-upload").prop("disabled", true);
|
||||
$("#btn-backup").prop("disabled", true);
|
||||
return $.ajax({
|
||||
method: "POST",
|
||||
url: "/api/v1/backup",
|
||||
timeout: 1800 * 1000
|
||||
}).done(function(data, e) {
|
||||
if (data) {
|
||||
return window.location = "/static_with_mime/" + data + "?mime=application/x-tgz";
|
||||
}
|
||||
}).fail(function(data, e) {
|
||||
var err, j;
|
||||
$("#request-error .alert").addClass("alert-danger");
|
||||
$("#request-error .alert").removeClass("alert-success");
|
||||
$("#request-error .alert").show();
|
||||
if ((data.responseText !== "") && (j = $.parseJSON(data.responseText)) && (err = j.error)) {
|
||||
return ($("#request-error .msg")).text("Server Error: " + err);
|
||||
} else {
|
||||
return ($("#request-error .msg")).text("The operation failed. Please reload the page and try again.");
|
||||
}
|
||||
}).always(function(data, e) {
|
||||
$("#btn-backup").text(btnText);
|
||||
$("#btn-upload").prop("disabled", false);
|
||||
return $("#btn-backup").prop("disabled", false);
|
||||
});
|
||||
});
|
||||
$("#btn-upload").click(function(e) {
|
||||
e.preventDefault();
|
||||
return $("[name='backup_upload']").click();
|
||||
});
|
||||
$("[name='backup_upload']").fileupload({
|
||||
url: "/api/v1/recover",
|
||||
progressall: function(e, data) {
|
||||
var valuenow;
|
||||
if (data.loaded && data.total) {
|
||||
valuenow = data.loaded / data.total * 100;
|
||||
$(".progress .bar").css("width", valuenow + "%");
|
||||
return $(".progress .bar").text("Uploading: " + Math.floor(valuenow) + "%");
|
||||
}
|
||||
},
|
||||
add: function(e, data) {
|
||||
$("#btn-upload").hide();
|
||||
$("#btn-backup").hide();
|
||||
$(".progress").show();
|
||||
return data.submit();
|
||||
},
|
||||
done: function(e, data) {
|
||||
var message;
|
||||
if ((data.jqXHR.responseText !== "") && (message = $.parseJSON(data.jqXHR.responseText))) {
|
||||
$("#request-error .alert").show();
|
||||
$("#request-error .alert").addClass("alert-success");
|
||||
$("#request-error .alert").removeClass("alert-danger");
|
||||
return ($("#request-error .msg")).text(message);
|
||||
}
|
||||
},
|
||||
fail: function(e, data) {
|
||||
var err, j;
|
||||
$("#request-error .alert").show();
|
||||
$("#request-error .alert").addClass("alert-danger");
|
||||
$("#request-error .alert").removeClass("alert-success");
|
||||
if ((data.jqXHR.responseText !== "") && (j = $.parseJSON(data.jqXHR.responseText)) && (err = j.error)) {
|
||||
return ($("#request-error .msg")).text("Server Error: " + err);
|
||||
} else {
|
||||
return ($("#request-error .msg")).text("The operation failed. Please reload the page and try again.");
|
||||
}
|
||||
},
|
||||
always: function(e, data) {
|
||||
$(".progress").hide();
|
||||
$("#btn-upload").show();
|
||||
return $("#btn-backup").show();
|
||||
}
|
||||
});
|
||||
$("#btn-reboot-system").click(function(e) {
|
||||
if (confirm("Are you sure you want to reboot your device?")) {
|
||||
return $.post("/api/v1/reboot").done(function(e) {
|
||||
($("#request-error .alert")).show();
|
||||
($("#request-error .alert")).addClass("alert-success");
|
||||
($("#request-error .alert")).removeClass("alert-danger");
|
||||
return ($("#request-error .msg")).text("Reboot has started successfully.");
|
||||
}).fail(function(data, e) {
|
||||
var err, j;
|
||||
($("#request-error .alert")).show();
|
||||
($("#request-error .alert")).addClass("alert-danger");
|
||||
($("#request-error .alert")).removeClass("alert-success");
|
||||
if ((data.responseText !== "") && (j = $.parseJSON(data.responseText)) && (err = j.error)) {
|
||||
return ($("#request-error .msg")).text("Server Error: " + err);
|
||||
} else {
|
||||
return ($("#request-error .msg")).text("The operation failed. Please reload the page and try again.");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
$("#btn-shutdown-system").click(function(e) {
|
||||
if (confirm("Are you sure you want to shutdown your device?")) {
|
||||
return $.post("/api/v1/shutdown").done(function(e) {
|
||||
($("#request-error .alert")).show();
|
||||
($("#request-error .alert")).addClass("alert-success");
|
||||
($("#request-error .alert")).removeClass("alert-danger");
|
||||
return ($("#request-error .msg")).text("Device shutdown has started successfully. Soon you will be able to unplug the power from your Raspberry Pi.");
|
||||
}).fail(function(data, e) {
|
||||
var err, j;
|
||||
($("#request-error .alert")).show();
|
||||
($("#request-error .alert")).addClass("alert-danger");
|
||||
($("#request-error .alert")).removeClass("alert-success");
|
||||
if ((data.responseText !== "") && (j = $.parseJSON(data.responseText)) && (err = j.error)) {
|
||||
return ($("#request-error .msg")).text("Server Error: " + err);
|
||||
} else {
|
||||
return ($("#request-error .msg")).text("The operation failed. Please reload the page and try again.");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
toggle_chunk = function() {
|
||||
$("[id^=auth_chunk]").hide();
|
||||
return $.each($('#auth_backend option'), function(e, t) {
|
||||
return $('#auth_backend-' + t.value).toggle($('#auth_backend').val() === t.value);
|
||||
});
|
||||
};
|
||||
$('#auth_backend').change(function(e) {
|
||||
return toggle_chunk();
|
||||
});
|
||||
return toggle_chunk();
|
||||
});
|
||||
|
||||
}).call(this);
|
||||
|
||||
//# sourceMappingURL=settings.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -282,6 +282,8 @@ def build_image(
|
||||
'libcups2',
|
||||
'libxcomposite1',
|
||||
'libxdamage1',
|
||||
'nodejs',
|
||||
'npm',
|
||||
],
|
||||
'chrome_dl_url': chrome_dl_url,
|
||||
'chromedriver_dl_url': chromedriver_dl_url,
|
||||
@@ -334,10 +336,9 @@ def build_image(
|
||||
],
|
||||
'archive_url': archive_url,
|
||||
})
|
||||
elif service == 'nginx':
|
||||
context.update({
|
||||
'environment': environment,
|
||||
})
|
||||
elif service == 'server':
|
||||
if environment == 'development':
|
||||
base_apt_dependencies.extend(['nodejs', 'npm'])
|
||||
|
||||
generate_dockerfile(service, {
|
||||
'base_image': base_image,
|
||||
@@ -346,6 +347,7 @@ def build_image(
|
||||
'board': board,
|
||||
'debian_version': 'bookworm',
|
||||
'disable_cache_mounts': disable_cache_mounts,
|
||||
'environment': environment,
|
||||
'git_branch': git_branch,
|
||||
'git_hash': git_hash,
|
||||
'git_short_hash': git_short_hash,
|
||||
|
||||
Reference in New Issue
Block a user